Merge pull request #193 from TeBoring/sb

Implement a feature to generate a dependency file
diff --git a/.gitignore b/.gitignore
index 3938196..cb0347f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@
 m4/ltsugar.m4
 m4/ltversion.m4
 m4/lt~obsolete.m4
+autom4te.cache
 
 # downloaded files
 gtest
@@ -23,7 +24,7 @@
 # in-tree configure-generated files
 Makefile
 src/Makefile
-config.h
+/config.h
 config.log
 config.status
 
@@ -38,6 +39,7 @@
 *.lo
 *.la
 src/.libs
+*.so
 
 .dirstamp
 
@@ -61,3 +63,13 @@
 src/testzip.*
 src/zcg*zip
 ar-lib
+
+test-driver
+compile
+
+src/**/*.log
+src/**/*.trs
+
+# JavaBuild output.
+java/target
+javanano/target
diff --git a/CHANGES.txt b/CHANGES.txt
index 0d4ce0e..ac42aa5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,85 @@
+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):
 
   General
diff --git a/Makefile.am b/Makefile.am
index 566b285..1c03923 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -154,10 +154,49 @@
   java/pom.xml                                                               \
   java/README.txt
 
+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.txt                                                                     \
+  javanano/pom.xml
+
+
 python_EXTRA_DIST=                                                           \
   python/google/protobuf/internal/api_implementation.cc                      \
   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/cpp_message.py                             \
   python/google/protobuf/internal/decoder.py                                 \
@@ -181,6 +220,7 @@
   python/google/protobuf/internal/more_extensions.proto                      \
   python/google/protobuf/internal/more_extensions_dynamic.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/python_message.py                          \
   python/google/protobuf/internal/reflection_test.py                         \
@@ -195,7 +235,6 @@
   python/google/protobuf/internal/wire_format.py                             \
   python/google/protobuf/internal/wire_format_test.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/inner.proto            \
   python/google/protobuf/internal/import_test_package/outer.proto            \
@@ -203,16 +242,17 @@
   python/google/protobuf/pyext/cpp_message.py                                \
   python/google/protobuf/pyext/descriptor.h                                  \
   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.cc                             \
   python/google/protobuf/pyext/message.h                                     \
   python/google/protobuf/pyext/message.cc                                    \
-  python/google/protobuf/pyext/message_factory_cpp2_test.py                  \
   python/google/protobuf/pyext/proto2_api_test.proto                         \
   python/google/protobuf/pyext/python.proto                                  \
   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.cc               \
   python/google/protobuf/pyext/repeated_scalar_container.h                   \
@@ -245,6 +285,7 @@
   ruby/ext/google/protobuf_c/defs.c                                          \
   ruby/ext/google/protobuf_c/encode_decode.c                                 \
   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/protobuf.c                                      \
   ruby/ext/google/protobuf_c/protobuf.h                                      \
@@ -255,9 +296,12 @@
   ruby/google-protobuf.gemspec                                               \
   ruby/lib/google/protobuf.rb                                                \
   ruby/tests/basic.rb                                                        \
-  ruby/tests/stress.rb
+  ruby/tests/stress.rb                                                       \
+  ruby/tests/generated_code.proto                                            \
+  ruby/tests/generated_code.rb                                               \
+  ruby/tests/generated_code_test.rb
 
-all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
+all_EXTRA_DIST=$(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
 
 EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST)                                       \
   autogen.sh                                                                 \
@@ -267,10 +311,12 @@
   LICENSE                                                                    \
   CONTRIBUTORS.txt                                                           \
   CHANGES.txt                                                                \
+  config.h.include                                                           \
   editors/README.txt                                                         \
   editors/proto.vim                                                          \
   editors/protobuf-mode.el                                                   \
   vsprojects/config.h                                                        \
+  vsprojects/google/protobuf/stubs/pbconfig.h                                \
   vsprojects/extract_includes.bat                                            \
   vsprojects/libprotobuf.vcproj                                              \
   vsprojects/libprotobuf-lite.vcproj                                         \
diff --git a/README.md b/README.md
index ae40679..5ea6aff 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,22 @@
   If you only want protobuf-lite, substitute "protobuf-lite" in place
   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**
 
   The makefiles normally invoke the protoc executable that they just
diff --git a/config.h.include b/config.h.include
new file mode 100644
index 0000000..0c557fb
--- /dev/null
+++ b/config.h.include
@@ -0,0 +1,7 @@
+HASH_MAP_CLASS
+HASH_MAP_H
+HASH_NAMESPACE
+HASH_SET_CLASS
+HASH_SET_H
+HAVE_HASH_MAP
+HAVE_HASH_SET
diff --git a/configure.ac b/configure.ac
index d1fde9d..14351a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,7 +12,7 @@
 # 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
 # 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-3-pre],[protobuf@googlegroups.com],[protobuf])
 
 AM_MAINTAINER_MODE([enable])
 
@@ -37,7 +37,7 @@
 
 AC_CANONICAL_TARGET
 
-AM_INIT_AUTOMAKE([subdir-objects])
+AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
 
 AC_ARG_WITH([zlib],
   [AS_HELP_STRING([--with-zlib],
@@ -54,7 +54,7 @@
 AC_PROG_CXX
 AC_LANG([C++])
 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
 
 # test_util.cc takes forever to compile with GCC and optimization turned on.
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index 07219dc..b25a3c6 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -27,7 +27,39 @@
 fi
 
 cd src
-make $@ protoc &&
-  ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto && \
-  ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto
+CORE_PROTO_IS_CORRECT=0
+while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
+do
+  CORE_PROTO_IS_CORRECT=1
+  cp google/protobuf/descriptor.pb.h google/protobuf/descriptor.pb.h.tmp
+  cp google/protobuf/descriptor.pb.cc google/protobuf/descriptor.pb.cc.tmp
+  cp google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp
+  cp google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp
+
+  make $@ protoc &&
+    ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto && \
+    ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto
+
+  diff google/protobuf/descriptor.pb.h google/protobuf/descriptor.pb.h.tmp > /dev/null
+  if test $? -ne 0; then
+    CORE_PROTO_IS_CORRECT=0
+  fi
+  diff google/protobuf/descriptor.pb.cc google/protobuf/descriptor.pb.cc.tmp > /dev/null
+  if test $? -ne 0; then
+    CORE_PROTO_IS_CORRECT=0
+  fi
+  diff google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp > /dev/null
+  if test $? -ne 0; then
+    CORE_PROTO_IS_CORRECT=0
+  fi
+  diff google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp > /dev/null
+  if test $? -ne 0; then
+    CORE_PROTO_IS_CORRECT=0
+  fi
+
+  rm google/protobuf/descriptor.pb.h.tmp
+  rm google/protobuf/descriptor.pb.cc.tmp
+  rm google/protobuf/compiler/plugin.pb.h.tmp
+  rm google/protobuf/compiler/plugin.pb.cc.tmp
+done
 cd ..
diff --git a/java/pom.xml b/java/pom.xml
index bbadc65..3eb7a70 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -10,7 +10,7 @@
   </parent>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java</artifactId>
-  <version>3.0.0-pre</version>
+  <version>3.0.0-alpha-3-pre</version>
   <packaging>bundle</packaging>
   <name>Protocol Buffer Java API</name>
   <description>
@@ -152,7 +152,7 @@
           <instructions>
             <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
             <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
-            <Export-Package>com.google.protobuf;version=3.0.0-pre</Export-Package>
+            <Export-Package>com.google.protobuf;version=3.0.0-alpha-3-pre</Export-Package>
           </instructions>
         </configuration>
       </plugin>
@@ -160,6 +160,64 @@
   </build>
   <profiles>
     <profile>
+      <id>release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <version>2.2.1</version>
+            <executions>
+              <execution>
+                <id>attach-sources</id>
+                <goals>
+                  <goal>jar-no-fork</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.9.1</version>
+            <executions>
+              <execution>
+                <id>attach-javadocs</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.5</version>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>nexus-staging-maven-plugin</artifactId>
+            <version>1.6.3</version>
+            <extensions>true</extensions>
+            <configuration>
+               <serverId>sonatype-nexus-staging</serverId>
+               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+               <autoReleaseAfterClose>false</autoReleaseAfterClose>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
       <id>lite</id>
       <build>
         <plugins>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index 6de4cae..cc89173 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -83,10 +83,10 @@
   }
 
   public void writeTo(final CodedOutputStream output) throws IOException {
-    MessageReflection.writeMessageTo(this, output, false);
+    MessageReflection.writeMessageTo(this, getAllFields(), output, false);
   }
 
-  private int memoizedSize = -1;
+  protected int memoizedSize = -1;
 
   public int getSerializedSize() {
     int size = memoizedSize;
@@ -94,7 +94,7 @@
       return size;
     }
 
-    memoizedSize = MessageReflection.getSerializedSize(this);
+    memoizedSize = MessageReflection.getSerializedSize(this, getAllFields());
     return memoizedSize;
   }
 
diff --git a/java/src/main/java/com/google/protobuf/BoundedByteString.java b/java/src/main/java/com/google/protobuf/BoundedByteString.java
index 8cb6f46..b4c3fb1 100644
--- a/java/src/main/java/com/google/protobuf/BoundedByteString.java
+++ b/java/src/main/java/com/google/protobuf/BoundedByteString.java
@@ -30,8 +30,8 @@
 
 package com.google.protobuf;
 
-import java.io.InvalidObjectException;
 import java.io.IOException;
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.util.NoSuchElementException;
 
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index cff1ee5..9b0a524 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -76,6 +76,9 @@
   static final int MIN_READ_FROM_CHUNK_SIZE = 0x100;  // 256b
   static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000;  // 8k
 
+  // Defined by java.nio.charset.Charset
+  protected static final String UTF_8 = "UTF-8";
+
   /**
    * Empty {@code ByteString}.
    */
@@ -267,7 +270,7 @@
    */
   public static ByteString copyFromUtf8(String text) {
     try {
-      return new LiteralByteString(text.getBytes("UTF-8"));
+      return new LiteralByteString(text.getBytes(UTF_8));
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported?", e);
     }
@@ -622,7 +625,7 @@
    */
   public String toStringUtf8() {
     try {
-      return toString("UTF-8");
+      return toString(UTF_8);
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported?", e);
     }
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index d65e8b4..806f46c 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -897,7 +897,7 @@
       return (type == Type.STRING) && (getFile().getOptions().getJavaStringCheckUtf8());
     }
 
-    boolean isMapField() {
+    public boolean isMapField() {
       return getType() == Type.MESSAGE && isRepeated()
           && getMessageType().getOptions().getMapEntry();
     }
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index 9c5e6c6..3ea1b68 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -35,8 +35,8 @@
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.Descriptors.OneofDescriptor;
 
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -600,9 +600,12 @@
       }
       // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not
       // set incorrect EnumValueDescriptors.
-      // if (field.getEnumType() != ((EnumValueDescriptor) value).getType()) {
-      //   throw new IllegalArgumentException(
-      //     "EnumValueDescriptor doesn't match Enum Field.");
+      // EnumDescriptor fieldType = field.getEnumType();
+      // EnumDescriptor fieldValueType = ((EnumValueDescriptor) value).getType();
+      // if (fieldType != fieldValueType) {
+      //  throw new IllegalArgumentException(String.format(
+      //      "EnumDescriptor %s of field doesn't match EnumDescriptor %s of field value",
+      //      fieldType.getFullName(), fieldValueType.getFullName()));
       // }
     }
 
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index ff9b5bc..47924b6 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -553,42 +553,13 @@
       CodedInputStream input,
       final WireFormat.FieldType type,
       boolean checkUtf8) throws IOException {
-    switch (type) {
-      case DOUBLE  : return input.readDouble  ();
-      case FLOAT   : return input.readFloat   ();
-      case INT64   : return input.readInt64   ();
-      case UINT64  : return input.readUInt64  ();
-      case INT32   : return input.readInt32   ();
-      case FIXED64 : return input.readFixed64 ();
-      case FIXED32 : return input.readFixed32 ();
-      case BOOL    : return input.readBool    ();
-      case STRING  : if (checkUtf8) {
-                       return input.readStringRequireUtf8();
-                     } else {
-                       return input.readString();
-                     }
-      case BYTES   : return input.readBytes   ();
-      case UINT32  : return input.readUInt32  ();
-      case SFIXED32: return input.readSFixed32();
-      case SFIXED64: return input.readSFixed64();
-      case SINT32  : return input.readSInt32  ();
-      case SINT64  : return input.readSInt64  ();
-
-      case GROUP:
-        throw new IllegalArgumentException(
-          "readPrimitiveField() cannot handle nested groups.");
-      case MESSAGE:
-        throw new IllegalArgumentException(
-          "readPrimitiveField() cannot handle embedded messages.");
-      case ENUM:
-        // We don't handle enums because we don't know what to do if the
-        // value is not recognized.
-        throw new IllegalArgumentException(
-          "readPrimitiveField() cannot handle enums.");
+    if (checkUtf8) {
+      return WireFormat.readPrimitiveField(input, type,
+          WireFormat.Utf8Validation.STRICT);
+    } else {
+      return WireFormat.readPrimitiveField(input, type,
+          WireFormat.Utf8Validation.LOOSE);
     }
-
-    throw new RuntimeException(
-      "There is no way to get here, but the compiler thinks otherwise.");
   }
 
 
@@ -685,9 +656,15 @@
       case FIXED64 : output.writeFixed64NoTag ((Long       ) value); break;
       case FIXED32 : output.writeFixed32NoTag ((Integer    ) value); break;
       case BOOL    : output.writeBoolNoTag    ((Boolean    ) value); break;
-      case STRING  : output.writeStringNoTag  ((String     ) value); break;
       case GROUP   : output.writeGroupNoTag   ((MessageLite) value); break;
       case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
+      case STRING:
+        if (value instanceof ByteString) {
+          output.writeBytesNoTag((ByteString) value);
+        } else {
+          output.writeStringNoTag((String) value);
+        }
+        break;
       case BYTES:
         if (value instanceof ByteString) {
           output.writeBytesNoTag((ByteString) value);
@@ -843,7 +820,6 @@
       case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long       )value);
       case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer    )value);
       case BOOL    : return CodedOutputStream.computeBoolSizeNoTag    ((Boolean    )value);
-      case STRING  : return CodedOutputStream.computeStringSizeNoTag  ((String     )value);
       case GROUP   : return CodedOutputStream.computeGroupSizeNoTag   ((MessageLite)value);
       case BYTES   :
         if (value instanceof ByteString) {
@@ -851,6 +827,12 @@
         } else {
           return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
         }
+      case STRING  :
+        if (value instanceof ByteString) {
+          return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+        } else {
+          return CodedOutputStream.computeStringSizeNoTag((String) value);
+        }
       case UINT32  : return CodedOutputStream.computeUInt32SizeNoTag  ((Integer    )value);
       case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer    )value);
       case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long       )value);
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 156d163..9457d99 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -73,7 +73,7 @@
 
   /** For use by generated code only.  */
   protected UnknownFieldSet unknownFields;
-  
+
   protected GeneratedMessage() {
     unknownFields = UnknownFieldSet.getDefaultInstance();
   }
@@ -109,8 +109,15 @@
     return internalGetFieldAccessorTable().descriptor;
   }
 
-  /** Internal helper which returns a mutable map. */
-  private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+  /**
+   * Internal helper to return a modifiable map containing all the fields.
+   * The returned Map is modifialbe so that the caller can add additional
+   * extension fields to implement {@link #getAllFields()}.
+   *
+   * @param getBytesForString whether to generate ByteString for string fields
+   */
+  private Map<FieldDescriptor, Object> getAllFieldsMutable(
+      boolean getBytesForString) {
     final TreeMap<FieldDescriptor, Object> result =
       new TreeMap<FieldDescriptor, Object>();
     final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
@@ -122,7 +129,12 @@
         }
       } else {
         if (hasField(field)) {
-          result.put(field, getField(field));
+          if (getBytesForString
+              && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+            result.put(field, getFieldRaw(field));
+          } else {
+            result.put(field, getField(field));
+          }
         }
       }
     }
@@ -161,7 +173,23 @@
 
   //@Override (Java 1.6 override semantics, but we must support 1.5)
   public Map<FieldDescriptor, Object> getAllFields() {
-    return Collections.unmodifiableMap(getAllFieldsMutable());
+    return Collections.unmodifiableMap(
+        getAllFieldsMutable(/* getBytesForString = */ false));
+  }
+
+  /**
+   * Returns a collection of all the fields in this message which are set
+   * and their corresponding values.  A singular ("required" or "optional")
+   * field is set iff hasField() returns true for that field.  A "repeated"
+   * field is set iff getRepeatedFieldCount() is greater than zero.  The
+   * values are exactly what would be returned by calling
+   * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field.  The map
+   * is guaranteed to be a sorted map, so iterating over it will return fields
+   * in order by field number.
+   */
+  Map<FieldDescriptor, Object> getAllFieldsRaw() {
+    return Collections.unmodifiableMap(
+        getAllFieldsMutable(/* getBytesForString = */ true));
   }
 
   //@Override (Java 1.6 override semantics, but we must support 1.5)
@@ -184,6 +212,18 @@
     return internalGetFieldAccessorTable().getField(field).get(this);
   }
 
+  /**
+   * Obtains the value of the given field, or the default value if it is
+   * not set.  For primitive fields, the boxed primitive value is returned.
+   * For enum fields, the EnumValueDescriptor for the value is returned. For
+   * embedded message fields, the sub-message is returned.  For repeated
+   * fields, a java.util.List is returned. For present string fields, a
+   * ByteString is returned representing the bytes that the field contains.
+   */
+  Object getFieldRaw(final FieldDescriptor field) {
+    return internalGetFieldAccessorTable().getField(field).getRaw(this);
+  }
+
   //@Override (Java 1.6 override semantics, but we must support 1.5)
   public int getRepeatedFieldCount(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field)
@@ -214,6 +254,24 @@
     return unknownFields.mergeFieldFrom(tag, input);
   }
 
+  @Override
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
+  }
+
+  @Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) {
+      return size;
+    }
+
+    memoizedSize = MessageReflection.getSerializedSize(
+        this, getAllFieldsRaw());
+    return memoizedSize;
+  }
+
+
 
   /**
    * Used by parsing constructors in generated classes.
@@ -549,12 +607,12 @@
      * Gets the map field with the given field number. This method should be
      * overridden in the generated message class if the message contains map
      * fields.
-     * 
+     *
      * Unlike other field types, reflection support for map fields can't be
      * implemented based on generated public API because we need to access a
      * map field as a list in reflection API but the generated API only allows
      * us to access it as a map. This method returns the underlying map field
-     * directly and thus enables us to access the map field as a list. 
+     * directly and thus enables us to access the map field as a list.
      */
     @SuppressWarnings({"unused", "rawtypes"})
     protected MapField internalGetMapField(int fieldNumber) {
@@ -563,6 +621,15 @@
       throw new RuntimeException(
           "No map fields found in " + getClass().getName());
     }
+
+    /** Like {@link internalGetMapField} but return a mutable version. */
+    @SuppressWarnings({"unused", "rawtypes"})
+    protected MapField internalGetMutableMapField(int fieldNumber) {
+      // Note that we can't use descriptor names here because this method will
+      // be called when descriptor is being initialized.
+      throw new RuntimeException(
+          "No map fields found in " + getClass().getName());
+    }
   }
 
   // =================================================================
@@ -683,7 +750,7 @@
     public final <Type> Type getExtension(
         final ExtensionLite<MessageType, Type> extensionLite) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
-      
+
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
       final Object value = extensions.getField(descriptor);
@@ -825,7 +892,16 @@
 
     @Override
     public Map<FieldDescriptor, Object> getAllFields() {
-      final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+      final Map<FieldDescriptor, Object> result =
+          super.getAllFieldsMutable(/* getBytesForString = */ false);
+      result.putAll(getExtensionFields());
+      return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFieldsRaw() {
+      final Map<FieldDescriptor, Object> result =
+          super.getAllFieldsMutable(/* getBytesForString = */ false);
       result.putAll(getExtensionFields());
       return Collections.unmodifiableMap(result);
     }
@@ -1313,7 +1389,7 @@
       implements ExtensionDescriptorRetriever {
     private volatile FieldDescriptor descriptor;
     protected abstract FieldDescriptor loadDescriptor();
-    
+
     public FieldDescriptor getDescriptor() {
       if (descriptor == null) {
         synchronized (this) {
@@ -1651,17 +1727,17 @@
       }
     }
   }
-  
+
   /**
    * Gets the map field with the given field number. This method should be
    * overridden in the generated message class if the message contains map
    * fields.
-   * 
+   *
    * Unlike other field types, reflection support for map fields can't be
    * implemented based on generated public API because we need to access a
    * map field as a list in reflection API but the generated API only allows
    * us to access it as a map. This method returns the underlying map field
-   * directly and thus enables us to access the map field as a list. 
+   * directly and thus enables us to access the map field as a list.
    */
   @SuppressWarnings({"rawtypes", "unused"})
   protected MapField internalGetMapField(int fieldNumber) {
@@ -1709,7 +1785,7 @@
       oneofs = new OneofAccessor[descriptor.getOneofs().size()];
       initialized = false;
     }
-    
+
     private boolean isMapFieldEnabled(FieldDescriptor field) {
       boolean result = true;
       return result;
@@ -1761,6 +1837,10 @@
               fields[i] = new SingularEnumFieldAccessor(
                   field, camelCaseNames[i], messageClass, builderClass,
                   containingOneofCamelCaseName);
+            } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+              fields[i] = new SingularStringFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass,
+                  containingOneofCamelCaseName);
             } else {
               fields[i] = new SingularFieldAccessor(
                   field, camelCaseNames[i], messageClass, builderClass,
@@ -1817,9 +1897,13 @@
     private interface FieldAccessor {
       Object get(GeneratedMessage message);
       Object get(GeneratedMessage.Builder builder);
+      Object getRaw(GeneratedMessage message);
+      Object getRaw(GeneratedMessage.Builder builder);
       void set(Builder builder, Object value);
       Object getRepeated(GeneratedMessage message, int index);
       Object getRepeated(GeneratedMessage.Builder builder, int index);
+      Object getRepeatedRaw(GeneratedMessage message, int index);
+      Object getRepeatedRaw(GeneratedMessage.Builder builder, int index);
       void setRepeated(Builder builder,
                        int index, Object value);
       void addRepeated(Builder builder, Object value);
@@ -1934,11 +2018,11 @@
       protected final FieldDescriptor field;
       protected final boolean isOneofField;
       protected final boolean hasHasMethod;
-      
+
       private int getOneofFieldNumber(final GeneratedMessage message) {
         return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
       }
-      
+
       private int getOneofFieldNumber(final GeneratedMessage.Builder builder) {
         return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
       }
@@ -1949,6 +2033,12 @@
       public Object get(GeneratedMessage.Builder builder) {
         return invokeOrDie(getMethodBuilder, builder);
       }
+      public Object getRaw(final GeneratedMessage message) {
+        return get(message);
+      }
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return get(builder);
+      }
       public void set(final Builder builder, final Object value) {
         invokeOrDie(setMethod, builder, value);
       }
@@ -1957,12 +2047,22 @@
         throw new UnsupportedOperationException(
           "getRepeatedField() called on a singular field.");
       }
+      public Object getRepeatedRaw(final GeneratedMessage message,
+                                final int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldRaw() called on a singular field.");
+      }
       public Object getRepeated(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
           "getRepeatedField() called on a singular field.");
       }
-      public void setRepeated(final Builder builder,
-                              final int index, final Object value) {
+      public Object getRepeatedRaw(GeneratedMessage.Builder builder,
+          int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldRaw() called on a singular field.");
+      }
+      public void setRepeated(final Builder builder, final int index,
+          final Object value) {
         throw new UnsupportedOperationException(
           "setRepeatedField() called on a singular field.");
       }
@@ -2058,6 +2158,12 @@
       public Object get(GeneratedMessage.Builder builder) {
         return invokeOrDie(getMethodBuilder, builder);
       }
+      public Object getRaw(final GeneratedMessage message) {
+        return get(message);
+      }
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return get(builder);
+      }
       public void set(final Builder builder, final Object value) {
         // Add all the elements individually.  This serves two purposes:
         // 1) Verifies that each element has the correct type.
@@ -2075,6 +2181,13 @@
       public Object getRepeated(GeneratedMessage.Builder builder, int index) {
         return invokeOrDie(getRepeatedMethodBuilder, builder, index);
       }
+      public Object getRepeatedRaw(GeneratedMessage message, int index) {
+        return getRepeated(message, index);
+      }
+      public Object getRepeatedRaw(GeneratedMessage.Builder builder,
+          int index) {
+        return getRepeated(builder, index);
+      }
       public void setRepeated(final Builder builder,
                               final int index, final Object value) {
         invokeOrDie(setRepeatedMethod, builder, index, value);
@@ -2130,15 +2243,21 @@
 
       private final FieldDescriptor field;
       private final Message mapEntryMessageDefaultInstance;
-      
+
       private MapField<?, ?> getMapField(GeneratedMessage message) {
         return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
       }
-      
+
       private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
         return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
       }
-      
+
+      private MapField<?, ?> getMutableMapField(
+          GeneratedMessage.Builder builder) {
+        return (MapField<?, ?>) builder.internalGetMutableMapField(
+            field.getNumber());
+      }
+
       public Object get(GeneratedMessage message) {
         List result = new ArrayList();
         for (int i = 0; i < getRepeatedCount(message); i++) {
@@ -2155,6 +2274,14 @@
         return Collections.unmodifiableList(result);
       }
 
+      public Object getRaw(GeneratedMessage message) {
+        return get(message);
+      }
+
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return get(builder);
+      }
+
       public void set(Builder builder, Object value) {
         clear(builder);
         for (Object entry : (List) value) {
@@ -2170,12 +2297,20 @@
         return getMapField(builder).getList().get(index);
       }
 
+      public Object getRepeatedRaw(GeneratedMessage message, int index) {
+        return getRepeated(message, index);
+      }
+
+      public Object getRepeatedRaw(Builder builder, int index) {
+        return getRepeated(builder, index);
+      }
+
       public void setRepeated(Builder builder, int index, Object value) {
-        getMapField(builder).getMutableList().set(index, (Message) value);
+        getMutableMapField(builder).getMutableList().set(index, (Message) value);
       }
 
       public void addRepeated(Builder builder, Object value) {
-        getMapField(builder).getMutableList().add((Message) value);
+        getMutableMapField(builder).getMutableList().add((Message) value);
       }
 
       public boolean has(GeneratedMessage message) {
@@ -2197,7 +2332,7 @@
       }
 
       public void clear(Builder builder) {
-        getMapField(builder).getMutableList().clear();
+        getMutableMapField(builder).getMutableList().clear();
       }
 
       public com.google.protobuf.Message.Builder newBuilder() {
@@ -2208,7 +2343,7 @@
         throw new UnsupportedOperationException(
             "Nested builder not supported for map fields.");
       }
-      
+
       public com.google.protobuf.Message.Builder getRepeatedBuilder(
           Builder builder, int index) {
         throw new UnsupportedOperationException(
@@ -2226,7 +2361,7 @@
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
         super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
-        
+
         enumDescriptor = descriptor.getEnumType();
 
         valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -2244,12 +2379,12 @@
               getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
         }
       }
-      
+
       private EnumDescriptor enumDescriptor;
 
       private Method valueOfMethod;
       private Method getValueDescriptorMethod;
-      
+
       private boolean supportUnknownEnumValue;
       private Method getValueMethod;
       private Method getValueMethodBuilder;
@@ -2291,7 +2426,7 @@
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
-        
+
         enumDescriptor = descriptor.getEnumType();
 
         valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -2315,7 +2450,7 @@
 
       private final Method valueOfMethod;
       private final Method getValueDescriptorMethod;
-      
+
       private boolean supportUnknownEnumValue;
       private Method getRepeatedValueMethod;
       private Method getRepeatedValueMethodBuilder;
@@ -2388,6 +2523,60 @@
 
     // ---------------------------------------------------------------
 
+    /**
+     * Field accessor for string fields.
+     *
+     * <p>This class makes getFooBytes() and setFooBytes() available for
+     * reflection API so that reflection based serialize/parse functions can
+     * access the raw bytes of the field to preserve non-UTF8 bytes in the
+     * string.
+     *
+     * <p>This ensures the serialize/parse round-trip safety, which is important
+     * for servers which forward messages.
+     */
+    private static final class SingularStringFieldAccessor
+        extends SingularFieldAccessor {
+      SingularStringFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass,
+          final String containingOneofCamelCaseName) {
+        super(descriptor, camelCaseName, messageClass, builderClass,
+            containingOneofCamelCaseName);
+        getBytesMethod = getMethodOrDie(messageClass,
+            "get" + camelCaseName + "Bytes");
+        getBytesMethodBuilder = getMethodOrDie(builderClass,
+            "get" + camelCaseName + "Bytes");
+        setBytesMethodBuilder = getMethodOrDie(builderClass,
+            "set" + camelCaseName + "Bytes", ByteString.class);
+      }
+
+      private final Method getBytesMethod;
+      private final Method getBytesMethodBuilder;
+      private final Method setBytesMethodBuilder;
+
+      @Override
+      public Object getRaw(final GeneratedMessage message) {
+        return invokeOrDie(getBytesMethod, message);
+      }
+
+      @Override
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return invokeOrDie(getBytesMethodBuilder, builder);
+      }
+
+      @Override
+      public void set(GeneratedMessage.Builder builder, Object value) {
+        if (value instanceof ByteString) {
+          invokeOrDie(setBytesMethodBuilder, builder, value);
+        } else {
+          super.set(builder, value);
+        }
+      }
+    }
+
+    // ---------------------------------------------------------------
+
     private static final class SingularMessageFieldAccessor
         extends SingularFieldAccessor {
       SingularMessageFieldAccessor(
@@ -2395,7 +2584,8 @@
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
-        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+        super(descriptor, camelCaseName, messageClass, builderClass,
+            containingOneofCamelCaseName);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
         getBuilderMethodBuilder =
@@ -2492,7 +2682,7 @@
   protected Object writeReplace() throws ObjectStreamException {
     return new GeneratedMessageLite.SerializedForm(this);
   }
-  
+
   /**
    * Checks that the {@link Extension} is non-Lite and returns it as a
    * {@link GeneratedExtension}.
@@ -2503,7 +2693,7 @@
     if (extension.isLite()) {
       throw new IllegalArgumentException("Expected non-lite extension.");
     }
-    
+
     return (Extension<MessageType, T>) extension;
   }
 }
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 4d25c07..6839c9d 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -42,22 +42,58 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Lite version of {@link GeneratedMessage}.
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class GeneratedMessageLite extends AbstractMessageLite
-    implements Serializable {
+public abstract class GeneratedMessageLite<
+    MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+    BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> 
+        extends AbstractMessageLite
+        implements Serializable {
+  
+  /**
+   * Holds all the {@link PrototypeHolder}s for loaded classes.
+   */
+  // TODO(dweis): Consider different concurrency values.
+  // TODO(dweis): This will prevent garbage collection of the class loader.
+  //     Ideally we'd use something like ClassValue but that's Java 7 only.
+  private static final Map<Class<?>, PrototypeHolder<?, ?>> PROTOTYPE_MAP =
+      new ConcurrentHashMap<Class<?>, PrototypeHolder<?, ?>>();
+  
+  // For use by generated code only.
+  protected static <
+      MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+      BuilderType extends GeneratedMessageLite.Builder<
+          MessageType, BuilderType>> void onLoad(Class<MessageType> clazz,
+              PrototypeHolder<MessageType, BuilderType> protoTypeHolder) {
+    PROTOTYPE_MAP.put(clazz, protoTypeHolder);
+  }
+
   private static final long serialVersionUID = 1L;
 
   /** For use by generated code only.  */
   protected UnknownFieldSetLite unknownFields;
   
-  public Parser<? extends MessageLite> getParserForType() {
-    throw new UnsupportedOperationException(
-        "This is supposed to be overridden by subclasses.");
+  @SuppressWarnings("unchecked") // Guaranteed by runtime.
+  public final Parser<MessageType> getParserForType() {
+    return (Parser<MessageType>) PROTOTYPE_MAP
+        .get(getClass()).getParserForType();
+  }
+
+  @SuppressWarnings("unchecked") // Guaranteed by runtime.
+  public final MessageType getDefaultInstanceForType() {
+    return (MessageType) PROTOTYPE_MAP
+        .get(getClass()).getDefaultInstanceForType();
+  }
+
+  @SuppressWarnings("unchecked") // Guaranteed by runtime.
+  public final BuilderType newBuilderForType() {
+    return (BuilderType) PROTOTYPE_MAP
+        .get(getClass()).newBuilderForType();
   }
 
   /**
@@ -73,10 +109,17 @@
     return unknownFields.mergeFieldFrom(tag, input);
   }
 
+  // The default behavior. If a message has required fields in its subtree, the
+  // generated code will override.
+  public boolean isInitialized() {
+    return true;
+  }
+
   @SuppressWarnings("unchecked")
-  public abstract static class Builder<MessageType extends GeneratedMessageLite,
-                                       BuilderType extends Builder>
-      extends AbstractMessageLite.Builder<BuilderType> {
+  public abstract static class Builder<
+      MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+      BuilderType extends Builder<MessageType, BuilderType>>
+          extends AbstractMessageLite.Builder<BuilderType> {
 
     private final MessageType defaultInstance;
 
@@ -88,6 +131,12 @@
       this.defaultInstance = defaultInstance;
     }
 
+    // The default behavior. If a message has required fields in its subtree,
+    // the generated code will override.
+    public boolean isInitialized() {
+      return true;
+    }
+
     //@Override (Java 1.6 override semantics, but we must support 1.5)
     public BuilderType clear() {
       unknownFields = UnknownFieldSetLite.getDefaultInstance();
@@ -174,7 +223,9 @@
    * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}.
    */
   public interface ExtendableMessageOrBuilder<
-      MessageType extends ExtendableMessage> extends MessageLiteOrBuilder {
+      MessageType extends ExtendableMessage<MessageType, BuilderType>,
+      BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+          extends MessageLiteOrBuilder {
 
     /** Check if a singular extension is present. */
     <Type> boolean hasExtension(
@@ -197,16 +248,30 @@
    * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
    */
   public abstract static class ExtendableMessage<
-        MessageType extends ExtendableMessage<MessageType>>
-      extends GeneratedMessageLite
-      implements ExtendableMessageOrBuilder<MessageType> {
+        MessageType extends ExtendableMessage<MessageType, BuilderType>,
+        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+            extends GeneratedMessageLite<MessageType, BuilderType>
+            implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
 
     /**
      * Represents the set of extensions on this message. For use by generated
      * code only.
      */
     protected FieldSet<ExtensionDescriptor> extensions = FieldSet.newFieldSet();
-    
+
+    // -1 => not memoized, 0 => false, 1 => true.
+    private byte memoizedIsInitialized = -1;
+
+    // The default behavior. If a message has required fields in its subtree,
+    // the generated code will override.
+    public boolean isInitialized() {
+      if (memoizedIsInitialized == -1) {
+        memoizedIsInitialized = (byte) (extensions.isInitialized() ? 1 : 0);
+      }
+
+      return memoizedIsInitialized == 1;
+    }
+
     private void verifyExtensionContainingType(
         final GeneratedExtension<MessageType, ?> extension) {
       if (extension.getContainingTypeDefaultInstance() !=
@@ -349,10 +414,10 @@
    */
   @SuppressWarnings("unchecked")
   public abstract static class ExtendableBuilder<
-        MessageType extends ExtendableMessage<MessageType>,
+        MessageType extends ExtendableMessage<MessageType, BuilderType>,
         BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
       extends Builder<MessageType, BuilderType>
-      implements ExtendableMessageOrBuilder<MessageType> {
+      implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
     protected ExtendableBuilder(MessageType defaultInstance) {
       super(defaultInstance);
     }
@@ -360,6 +425,12 @@
     private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
     private boolean extensionsIsMutable;
 
+    // The default behavior. If a message has required fields in its subtree,
+    // the generated code will override.
+    public boolean isInitialized() {
+      return extensions.isInitialized();
+    }
+
     // For immutable message conversion.
     void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
       this.extensions = extensions;
@@ -991,7 +1062,10 @@
    * Checks that the {@link Extension} is Lite and returns it as a
    * {@link GeneratedExtension}.
    */
-  private static <MessageType extends ExtendableMessage<MessageType>, T>
+  private static <
+      MessageType extends ExtendableMessage<MessageType, BuilderType>,
+      BuilderType extends ExtendableBuilder<MessageType, BuilderType>,
+      T>
     GeneratedExtension<MessageType, T> checkIsLite(
         ExtensionLite<MessageType, T> extension) {
     if (!extension.isLite()) {
@@ -1000,4 +1074,43 @@
     
     return (GeneratedExtension<MessageType, T>) extension;
   }
+  
+  /**
+   * Represents the state needed to implement *ForType methods. Generated code
+   * must provide a static singleton instance by adding it with
+   * {@link GeneratedMessageLite#onLoad(Class, PrototypeHolder)} on class load.
+   * <ul>
+   * <li>{@link #getDefaultInstanceForType()}
+   * <li>{@link #getParserForType()}
+   * <li>{@link #newBuilderForType()}
+   * </ul>
+   * This allows us to trade three generated methods for a static Map.
+   */
+  protected static class PrototypeHolder<
+      MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+      BuilderType extends GeneratedMessageLite.Builder<
+          MessageType, BuilderType>> {
+    
+    private final MessageType defaultInstance;
+    private final Parser<MessageType> parser;
+    
+    public PrototypeHolder(
+        MessageType defaultInstance, Parser<MessageType> parser) {
+      this.defaultInstance = defaultInstance;
+      this.parser = parser;
+    }
+    
+    public MessageType getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    public Parser<MessageType> getParserForType() {
+      return parser;
+    }
+
+    @SuppressWarnings("unchecked") // Guaranteed by runtime.
+    public BuilderType newBuilderForType() {
+      return (BuilderType) defaultInstance.toBuilder();
+    }
+  }
 }
diff --git a/java/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/src/main/java/com/google/protobuf/LazyFieldLite.java
index 1fc80e8..eea1fe3 100644
--- a/java/src/main/java/com/google/protobuf/LazyFieldLite.java
+++ b/java/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -30,8 +30,6 @@
 
 package com.google.protobuf;
 
-import java.io.IOException;
-
 /**
  * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores
  * the message in a ByteString initially and then parse it on-demand.
@@ -44,40 +42,102 @@
  * @author xiangl@google.com (Xiang Li)
  */
 public class LazyFieldLite {
-  private ByteString bytes;
-  private ExtensionRegistryLite extensionRegistry;
-  private volatile boolean isDirty = false;
+  private static final ExtensionRegistryLite EMPTY_REGISTRY =
+      ExtensionRegistryLite.getEmptyRegistry();
 
+  /**
+   * A delayed-parsed version of the bytes. When this is non-null then {@code extensionRegistry } is
+   * also non-null and {@code value} and {@code memoizedBytes} are null.
+   */
+  private ByteString delayedBytes;
+
+  /**
+   * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It
+   * is only guaranteed to be non-null if this message was initialized using bytes and an
+   * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has
+   * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}.
+   */
+  private ExtensionRegistryLite extensionRegistry;
+
+  /**
+   * The parsed value. When this is non-null then {@code delayedBytes} will be null.
+   */
   protected volatile MessageLite value;
 
+  /**
+   * The memoized bytes for {@code value}. Will be null when {@code value} is null.
+   */
+  private volatile ByteString memoizedBytes;
+
+  /**
+   * Constructs a LazyFieldLite with bytes that will be parsed lazily.
+   */
   public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+    checkArguments(extensionRegistry, bytes);
     this.extensionRegistry = extensionRegistry;
-    this.bytes = bytes;
+    this.delayedBytes = bytes;
   }
 
+  /**
+   * Constructs a LazyFieldLite with no contents, and no ability to parse extensions.
+   */
   public LazyFieldLite() {
   }
 
+  /**
+   * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse
+   * the extensions in the value as it has no ExtensionRegistry.
+   */
   public static LazyFieldLite fromValue(MessageLite value) {
     LazyFieldLite lf = new LazyFieldLite();
     lf.setValue(value);
     return lf;
   }
 
+  /**
+   * Determines whether this LazyFieldLite instance represents the default instance of this type.
+   */
   public boolean containsDefaultInstance() {
-    return value == null && bytes == null;
-  }
-
-  public void clear() {
-    bytes = null;
-    value = null;
-    extensionRegistry = null;
-    isDirty = true;
+    return memoizedBytes == ByteString.EMPTY
+        || value == null && (delayedBytes == null || delayedBytes == ByteString.EMPTY);
   }
 
   /**
-   * Returns message instance. At first time, serialized data is parsed by
-   * {@code defaultInstance.getParserForType()}.
+   * Clears the value state of this instance.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void clear() {
+    // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another
+    // value, but there is no guarantee that it will contain all extensions that were directly set
+    // on the values that need to be merged.
+    delayedBytes = null;
+    value = null;
+    memoizedBytes = null;
+  }
+
+  /**
+   * Overrides the contents of this LazyField.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void set(LazyFieldLite other) {
+    this.delayedBytes = other.delayedBytes;
+    this.value = other.value;
+    this.memoizedBytes = other.memoizedBytes;
+    // If the other LazyFieldLite was created by directly setting the value rather than first by
+    // parsing, then it will not have an extensionRegistry. In this case we hold on to the existing
+    // extensionRegistry, which has no guarantees that it has all the extensions that will be
+    // directly set on the value.
+    if (other.extensionRegistry != null) {
+      this.extensionRegistry = other.extensionRegistry;
+    }
+  }
+
+  /**
+   * Returns message instance. It may do some thread-safe delayed parsing of bytes.
    *
    * @param defaultInstance its message's default instance. It's also used to get parser for the
    * message type.
@@ -88,38 +148,109 @@
   }
 
   /**
-   * LazyField is not thread-safe for write access. Synchronizations are needed
+   * Sets the value of the instance and returns the old value without delay parsing anything.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
    * under read/write situations.
    */
   public MessageLite setValue(MessageLite value) {
     MessageLite originalValue = this.value;
+    this.delayedBytes = null;
+    this.memoizedBytes = null;
     this.value = value;
-    bytes = null;
-    isDirty = true;
     return originalValue;
   }
 
-  public void merge(LazyFieldLite value) {
-    if (value.containsDefaultInstance()) {
+  /**
+   * Merges another instance's contents. In some cases may drop some extensions if both fields
+   * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this
+   * field will copy over that {@code ExtensionRegistry}.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void merge(LazyFieldLite other) {
+    if (other.containsDefaultInstance()) {
       return;
     }
 
-    if (bytes == null) {
-      this.bytes = value.bytes;
-    } else {
-      this.bytes.concat(value.toByteString());
+    if (this.containsDefaultInstance()) {
+      set(other);
+      return;
     }
-    isDirty = false;
+
+    // If the other field has an extension registry but this does not, copy over the other extension
+    // registry.
+    if (this.extensionRegistry == null) {
+      this.extensionRegistry = other.extensionRegistry;
+    }
+
+    // In the case that both of them are not parsed we simply concatenate the bytes to save time. In
+    // the (probably rare) case that they have different extension registries there is a chance that
+    // some of the extensions may be dropped, but the tradeoff of making this operation fast seems
+    // to outway the benefits of combining the extension registries, which is not normally done for
+    // lite protos anyways.
+    if (this.delayedBytes != null && other.delayedBytes != null) {
+      this.delayedBytes = this.delayedBytes.concat(other.delayedBytes);
+      return;
+    }
+
+    // At least one is parsed and both contain data. We won't drop any extensions here directly, but
+    // in the case that the extension registries are not the same then we might in the future if we
+    // need to serialze and parse a message again.
+    if (this.value == null && other.value != null) {
+      setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry));
+      return;
+    } else if (this.value != null && other.value == null) {
+      setValue(mergeValueAndBytes(this.value, other.delayedBytes, other.extensionRegistry));
+      return;
+    }
+
+    // At this point we have two fully parsed messages. We can't merge directly from one to the
+    // other because only generated builder code contains methods to mergeFrom another parsed
+    // message. We have to serialize one instance and then merge the bytes into the other. This may
+    // drop extensions from one of the messages if one of the values had an extension set on it
+    // directly.
+    //
+    // To mitigate this we prefer serializing a message that has an extension registry, and
+    // therefore a chance that all extensions set on it are in that registry.
+    //
+    // NOTE: The check for other.extensionRegistry not being null must come first because at this
+    // point in time if other.extensionRegistry is not null then this.extensionRegistry will not be
+    // null either.
+    if (other.extensionRegistry != null) {
+      setValue(mergeValueAndBytes(this.value, other.toByteString(), other.extensionRegistry));
+      return;
+    } else if (this.extensionRegistry != null) {
+      setValue(mergeValueAndBytes(other.value, this.toByteString(), this.extensionRegistry));
+      return;
+    } else {
+      // All extensions from the other message will be dropped because we have no registry.
+      setValue(mergeValueAndBytes(this.value, other.toByteString(), EMPTY_REGISTRY));
+      return;
+    }
   }
 
+  private static MessageLite mergeValueAndBytes(
+      MessageLite value, ByteString otherBytes, ExtensionRegistryLite extensionRegistry) {
+    try {
+      return value.toBuilder().mergeFrom(otherBytes, extensionRegistry).build();
+    } catch (InvalidProtocolBufferException e) {
+      // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto
+      // was invalid.
+      return value;
+    }
+  }
+
+  /**
+   * Sets this field with bytes to delay-parse.
+   */
   public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) {
-    this.bytes = bytes;
+    checkArguments(extensionRegistry, bytes);
+    this.delayedBytes = bytes;
     this.extensionRegistry = extensionRegistry;
-    isDirty = false;
-  }
-
-  public ExtensionRegistryLite getExtensionRegistry() {
-    return extensionRegistry;
+    this.value = null;
+    this.memoizedBytes = null;
   }
 
   /**
@@ -128,30 +259,43 @@
    * parsed. Be careful when using this method.
    */
   public int getSerializedSize() {
-    if (isDirty) {
+    if (delayedBytes != null) {
+      return delayedBytes.size();
+    } else if (memoizedBytes != null) {
+      return memoizedBytes.size();
+    } else if (value != null) {
       return value.getSerializedSize();
+    } else {
+      return 0;
     }
-    return bytes.size();
   }
 
+  /**
+   * Returns a BytesString for this field in a thread-safe way.
+   */
   public ByteString toByteString() {
-    if (!isDirty) {
-      return bytes;
+    if (delayedBytes != null) {
+      return delayedBytes;
+    }
+    if (memoizedBytes != null) {
+      return memoizedBytes;
     }
     synchronized (this) {
-      if (!isDirty) {
-        return bytes;
+      if (memoizedBytes != null) {
+        return memoizedBytes;
       }
       if (value == null) {
-        bytes = ByteString.EMPTY;
+        memoizedBytes = ByteString.EMPTY;
       } else {
-        bytes = value.toByteString();
+        memoizedBytes = value.toByteString();
       }
-      isDirty = false;
-      return bytes;
+      return memoizedBytes;
     }
   }
 
+  /**
+   * Might lazily parse the bytes that were previously passed in. Is thread-safe.
+   */
   protected void ensureInitialized(MessageLite defaultInstance) {
     if (value != null) {
       return;
@@ -161,16 +305,35 @@
         return;
       }
       try {
-        if (bytes != null) {
-          value = defaultInstance.getParserForType()
-              .parseFrom(bytes, extensionRegistry);
+        if (delayedBytes != null) {
+          // The extensionRegistry shouldn't be null here since we have delayedBytes.
+          MessageLite parsedValue = defaultInstance.getParserForType()
+              .parseFrom(delayedBytes, extensionRegistry);
+          this.value = parsedValue;
+          this.memoizedBytes = delayedBytes;
+          this.delayedBytes = null;
         } else {
-          value = defaultInstance;
+          this.value = defaultInstance;
+          this.memoizedBytes = ByteString.EMPTY;
+          this.delayedBytes = null;
         }
-      } catch (IOException e) {
-        // TODO(xiangl): Refactory the API to support the exception thrown from
-        // lazily load messages.
+      } catch (InvalidProtocolBufferException e) {
+        // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto
+        // was invalid.
+        this.value = defaultInstance;
+        this.memoizedBytes = ByteString.EMPTY;
+        this.delayedBytes = null;
       }
     }
   }
+
+
+  private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+    if (extensionRegistry == null) {
+      throw new NullPointerException("found null ExtensionRegistry");
+    }
+    if (bytes == null) {
+      throw new NullPointerException("found null ByteString");
+    }
+  }
 }
diff --git a/java/src/main/java/com/google/protobuf/LiteralByteString.java b/java/src/main/java/com/google/protobuf/LiteralByteString.java
index 767b9f3..6893ddf 100644
--- a/java/src/main/java/com/google/protobuf/LiteralByteString.java
+++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java
@@ -154,7 +154,11 @@
   @Override
   public String toString(String charsetName)
       throws UnsupportedEncodingException {
-    return new String(bytes, getOffsetIntoBytes(), size(), charsetName);
+    // Optimize for empty strings, but ensure we don't silently ignore invalid
+    // encodings.
+    return size() == 0 && UTF_8.equals(charsetName)
+        ? ""
+        : new String(bytes, getOffsetIntoBytes(), size(), charsetName);
   }
 
   // =================================================================
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 5c75b58..fa0265e 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -163,7 +163,7 @@
      * field builder, which will then be nested into its parent builder.
      * <p>
      * NOTE: implementations that do not support nested builders will throw
-     * <code>UnsupportedException</code>.
+     * <code>UnsupportedOperationException</code>.
      */
     Builder getFieldBuilder(Descriptors.FieldDescriptor field);
 
@@ -181,7 +181,7 @@
      * field builder, which will then be nested into its parent builder.
      * <p>
      * NOTE: implementations that do not support nested builders will throw
-     * <code>UnsupportedException</code>.
+     * <code>UnsupportedOperationException</code>.
      */
     Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field,
                                     int index);
diff --git a/java/src/main/java/com/google/protobuf/MessageReflection.java b/java/src/main/java/com/google/protobuf/MessageReflection.java
index 06e3c99..de4bfd3 100644
--- a/java/src/main/java/com/google/protobuf/MessageReflection.java
+++ b/java/src/main/java/com/google/protobuf/MessageReflection.java
@@ -45,13 +45,14 @@
  */
 class MessageReflection {
 
-  static void writeMessageTo(Message message, CodedOutputStream output,
+  static void writeMessageTo(
+      Message message,
+      Map<FieldDescriptor, Object> fields,
+      CodedOutputStream output,
       boolean alwaysWriteRequiredFields)
       throws IOException {
     final boolean isMessageSet =
         message.getDescriptorForType().getOptions().getMessageSetWireFormat();
-
-    Map<FieldDescriptor, Object> fields = message.getAllFields();
     if (alwaysWriteRequiredFields) {
       fields = new TreeMap<FieldDescriptor, Object>(fields);
       for (final FieldDescriptor field :
@@ -82,13 +83,15 @@
     }
   }
 
-  static int getSerializedSize(Message message) {
+  static int getSerializedSize(
+      Message message,
+      Map<FieldDescriptor, Object> fields) {
     int size = 0;
     final boolean isMessageSet =
         message.getDescriptorForType().getOptions().getMessageSetWireFormat();
 
     for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
-        message.getAllFields().entrySet()) {
+        fields.entrySet()) {
       final Descriptors.FieldDescriptor field = entry.getKey();
       final Object value = entry.getValue();
       if (isMessageSet && field.isExtension() &&
@@ -340,14 +343,12 @@
         ByteString bytes, ExtensionRegistryLite registry,
         Descriptors.FieldDescriptor descriptor, Message defaultInstance)
         throws IOException;
-    
+
     /**
-     * Read a primitive field from input. Note that builders and mutable
-     * messages may use different Java types to represent a primtive field.
+     * Returns the UTF8 validation level for the field.
      */
-    Object readPrimitiveField(
-        CodedInputStream input, WireFormat.FieldType type,
-        boolean checkUtf8) throws IOException;
+    WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor
+        descriptor);
 
     /**
      * Returns a new merge target for a sub-field. When defaultInstance is
@@ -513,11 +514,18 @@
         return new BuilderAdapter(builder.newBuilderForField(field));
       }
     }
-    
-    public Object readPrimitiveField(
-        CodedInputStream input, WireFormat.FieldType type,
-        boolean checkUtf8) throws IOException {
-      return FieldSet.readPrimitiveField(input, type, checkUtf8);
+
+    public WireFormat.Utf8Validation
+        getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+      if (descriptor.needsUtf8Check()) {
+        return WireFormat.Utf8Validation.STRICT;
+      }
+      // TODO(liujisi): support lazy strings for repeated fields.
+      if (!descriptor.isRepeated()
+          && builder instanceof GeneratedMessage.Builder) {
+        return WireFormat.Utf8Validation.LAZY;
+      }
+      return WireFormat.Utf8Validation.LOOSE;
     }
 
     public Object finish() {
@@ -651,11 +659,14 @@
       throw new UnsupportedOperationException(
           "newMergeTargetForField() called on FieldSet object");
     }
-    
-    public Object readPrimitiveField(
-        CodedInputStream input, WireFormat.FieldType type,
-        boolean checkUtf8) throws IOException {
-      return FieldSet.readPrimitiveField(input, type, checkUtf8);
+
+    public WireFormat.Utf8Validation
+        getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+      if (descriptor.needsUtf8Check()) {
+        return WireFormat.Utf8Validation.STRICT;
+      }
+      // TODO(liujisi): support lazy strings for ExtesnsionSet.
+      return WireFormat.Utf8Validation.LOOSE;
     }
 
     public Object finish() {
@@ -767,8 +778,8 @@
         }
       } else {
         while (input.getBytesUntilLimit() > 0) {
-          final Object value =
-              target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
+          final Object value = WireFormat.readPrimitiveField(
+              input, field.getLiteType(), target.getUtf8Validation(field));
           target.addRepeatedField(field, value);
         }
       }
@@ -801,7 +812,8 @@
           }
           break;
         default:
-          value = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
+          value = WireFormat.readPrimitiveField(
+              input, field.getLiteType(), target.getUtf8Validation(field));
           break;
       }
 
diff --git a/java/src/main/java/com/google/protobuf/Parser.java b/java/src/main/java/com/google/protobuf/Parser.java
index f636014..227c02b 100644
--- a/java/src/main/java/com/google/protobuf/Parser.java
+++ b/java/src/main/java/com/google/protobuf/Parser.java
@@ -227,8 +227,8 @@
    * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write
    * messages in this format.
    *
-   * @return True if successful, or false if the stream is at EOF when the
-   *         method starts. Any other error (including reaching EOF during
+   * @return Parsed message if successful, or null if the stream is at EOF when
+   *         the method starts. Any other error (including reaching EOF during
    *         parsing) will cause an exception to be thrown.
    */
   public MessageType parseDelimitedFrom(InputStream input)
diff --git a/java/src/main/java/com/google/protobuf/RopeByteString.java b/java/src/main/java/com/google/protobuf/RopeByteString.java
index fa23c9d..168bcce 100644
--- a/java/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/src/main/java/com/google/protobuf/RopeByteString.java
@@ -30,9 +30,9 @@
 
 package com.google.protobuf;
 
-import java.io.InvalidObjectException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
@@ -420,7 +420,11 @@
   @Override
   public String toString(String charsetName)
       throws UnsupportedEncodingException {
-    return new String(toByteArray(), charsetName);
+    // Optimize for empty strings, but ensure we don't silently ignore invalid
+    // encodings.
+    return size() == 0 && UTF_8.equals(charsetName)
+        ? ""
+        : new String(toByteArray(), charsetName);
   }
 
   // =================================================================
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 4f6756e..dd2b460 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -409,9 +409,9 @@
 
         case STRING:
           generator.print("\"");
-          generator.print(escapeNonAscii ?
-              escapeText((String) value) :
-              escapeDoubleQuotesAndBackslashes((String) value)
+          generator.print(escapeNonAscii
+              ? escapeText((String) value)
+              : escapeDoubleQuotesAndBackslashes((String) value)
                   .replace("\n", "\\n"));
           generator.print("\"");
           break;
@@ -730,8 +730,8 @@
       }
 
       final char c = currentToken.charAt(0);
-      return ('0' <= c && c <= '9') ||
-             c == '-' || c == '+';
+      return ('0' <= c && c <= '9')
+          || c == '-' || c == '+';
     }
 
     /**
@@ -749,10 +749,10 @@
     public String consumeIdentifier() throws ParseException {
       for (int i = 0; i < currentToken.length(); i++) {
         final char c = currentToken.charAt(i);
-        if (('a' <= c && c <= 'z') ||
-            ('A' <= c && c <= 'Z') ||
-            ('0' <= c && c <= '9') ||
-            (c == '_') || (c == '.')) {
+        if (('a' <= c && c <= 'z')
+            || ('A' <= c && c <= 'Z')
+            || ('0' <= c && c <= '9')
+            || (c == '_') || (c == '.')) {
           // OK
         } else {
           throw parseException(
@@ -941,14 +941,14 @@
      * Otherwise, throw a {@link ParseException}.
      */
     public boolean consumeBoolean() throws ParseException {
-      if (currentToken.equals("true") ||
-          currentToken.equals("t") ||
-          currentToken.equals("1")) {
+      if (currentToken.equals("true")
+          || currentToken.equals("t")
+          || currentToken.equals("1")) {
         nextToken();
         return true;
-      } else if (currentToken.equals("false") ||
-                 currentToken.equals("f") ||
-                 currentToken.equals("0")) {
+      } else if (currentToken.equals("false")
+          || currentToken.equals("f")
+          || currentToken.equals("0")) {
         nextToken();
         return false;
       } else {
@@ -999,14 +999,15 @@
      */
     private void consumeByteString(List<ByteString> list)
         throws ParseException {
-      final char quote = currentToken.length() > 0 ? currentToken.charAt(0)
-                                                   : '\0';
+      final char quote = currentToken.length() > 0
+          ? currentToken.charAt(0)
+          : '\0';
       if (quote != '\"' && quote != '\'') {
         throw parseException("Expected string.");
       }
 
-      if (currentToken.length() < 2 ||
-          currentToken.charAt(currentToken.length() - 1) != quote) {
+      if (currentToken.length() < 2
+          || currentToken.charAt(currentToken.length() - 1) != quote) {
         throw parseException("String missing ending quote.");
       }
 
@@ -1340,8 +1341,8 @@
         } else {
           if (extension.descriptor.getContainingType() != type) {
             throw tokenizer.parseExceptionPreviousToken(
-              "Extension \"" + name + "\" does not extend message type \"" +
-              type.getFullName() + "\".");
+              "Extension \"" + name + "\" does not extend message type \""
+              + type.getFullName() + "\".");
           }
           field = extension.descriptor;
         }
@@ -1365,20 +1366,20 @@
           }
         }
         // Again, special-case group names as described above.
-        if (field != null && field.getType() == FieldDescriptor.Type.GROUP &&
-            !field.getMessageType().getName().equals(name)) {
+        if (field != null && field.getType() == FieldDescriptor.Type.GROUP
+            && !field.getMessageType().getName().equals(name)) {
           field = null;
         }
 
         if (field == null) {
           if (!allowUnknownFields) {
             throw tokenizer.parseExceptionPreviousToken(
-              "Message type \"" + type.getFullName() +
-              "\" has no field named \"" + name + "\".");
+              "Message type \"" + type.getFullName()
+              + "\" has no field named \"" + name + "\".");
           } else {
             logger.warning(
-              "Message type \"" + type.getFullName() +
-              "\" has no field named \"" + name + "\".");
+              "Message type \"" + type.getFullName()
+              + "\" has no field named \"" + name + "\".");
           }
         }
       }
@@ -1391,8 +1392,9 @@
         // start with "{" or "<" which indicates the beginning of a message body.
         // If there is no ":" or there is a "{" or "<" after ":", this field has
         // to be a message or the input is ill-formed.
-        if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") &&
-            !tokenizer.lookingAt("<")) {
+        if (tokenizer.tryConsume(":")
+            && !tokenizer.lookingAt("{")
+            && !tokenizer.lookingAt("<")) {
           skipFieldValue(tokenizer);
         } else {
           skipFieldMessage(tokenizer);
@@ -1516,16 +1518,16 @@
               value = enumType.findValueByNumber(number);
               if (value == null) {
                 throw tokenizer.parseExceptionPreviousToken(
-                  "Enum type \"" + enumType.getFullName() +
-                  "\" has no value with number " + number + '.');
+                  "Enum type \"" + enumType.getFullName()
+                  + "\" has no value with number " + number + '.');
               }
             } else {
               final String id = tokenizer.consumeIdentifier();
               value = enumType.findValueByName(id);
               if (value == null) {
                 throw tokenizer.parseExceptionPreviousToken(
-                  "Enum type \"" + enumType.getFullName() +
-                  "\" has no value named \"" + id + "\".");
+                  "Enum type \"" + enumType.getFullName()
+                  + "\" has no value named \"" + id + "\".");
               }
             }
 
@@ -1578,8 +1580,9 @@
       // start with "{" or "<" which indicates the beginning of a message body.
       // If there is no ":" or there is a "{" or "<" after ":", this field has
       // to be a message or the input is ill-formed.
-      if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") &&
-          !tokenizer.lookingAt("{")) {
+      if (tokenizer.tryConsume(":")
+          && !tokenizer.lookingAt("<")
+          && !tokenizer.lookingAt("{")) {
         skipFieldValue(tokenizer);
       } else {
         skipFieldMessage(tokenizer);
@@ -1617,11 +1620,11 @@
         while (tokenizer.tryConsumeString()) {}
         return;
       }
-      if (!tokenizer.tryConsumeIdentifier() &&  // includes enum & boolean
-          !tokenizer.tryConsumeInt64() &&       // includes int32
-          !tokenizer.tryConsumeUInt64() &&      // includes uint32
-          !tokenizer.tryConsumeDouble() &&
-          !tokenizer.tryConsumeFloat()) {
+      if (!tokenizer.tryConsumeIdentifier()   // includes enum & boolean
+          && !tokenizer.tryConsumeInt64()     // includes int32
+          && !tokenizer.tryConsumeUInt64()    // includes uint32
+          && !tokenizer.tryConsumeDouble()
+          && !tokenizer.tryConsumeFloat()) {
         throw tokenizer.parseException(
             "Invalid field value: " + tokenizer.currentToken);
       }
@@ -1647,19 +1650,19 @@
    * which no defined short-hand escape sequence is defined will be escaped
    * using 3-digit octal sequences.
    */
-  private static String escapeBytes(final ByteSequence input) {
+  public static String escapeBytes(final ByteSequence input) {
     final StringBuilder builder = new StringBuilder(input.size());
     for (int i = 0; i < input.size(); i++) {
       final byte b = input.byteAt(i);
       switch (b) {
         // Java does not recognize \a or \v, apparently.
-        case 0x07: builder.append("\\a" ); break;
-        case '\b': builder.append("\\b" ); break;
-        case '\f': builder.append("\\f" ); break;
-        case '\n': builder.append("\\n" ); break;
-        case '\r': builder.append("\\r" ); break;
-        case '\t': builder.append("\\t" ); break;
-        case 0x0b: builder.append("\\v" ); break;
+        case 0x07: builder.append("\\a"); break;
+        case '\b': builder.append("\\b"); break;
+        case '\f': builder.append("\\f"); break;
+        case '\n': builder.append("\\n"); break;
+        case '\r': builder.append("\\r"); break;
+        case '\t': builder.append("\\t"); break;
+        case 0x0b: builder.append("\\v"); break;
         case '\\': builder.append("\\\\"); break;
         case '\'': builder.append("\\\'"); break;
         case '"' : builder.append("\\\""); break;
@@ -1688,11 +1691,13 @@
    * which no defined short-hand escape sequence is defined will be escaped
    * using 3-digit octal sequences.
    */
-  static String escapeBytes(final ByteString input) {
+  public static String escapeBytes(final ByteString input) {
     return escapeBytes(new ByteSequence() {
+      @Override
       public int size() {
         return input.size();
       }
+      @Override
       public byte byteAt(int offset) {
         return input.byteAt(offset);
       }
@@ -1702,11 +1707,13 @@
   /**
    * Like {@link #escapeBytes(ByteString)}, but used for byte array.
    */
-  static String escapeBytes(final byte[] input) {
+  public static String escapeBytes(final byte[] input) {
     return escapeBytes(new ByteSequence() {
+      @Override
       public int size() {
         return input.length;
       }
+      @Override
       public byte byteAt(int offset) {
         return input[offset];
       }
@@ -1749,7 +1756,7 @@
               code = code * 8 + digitValue(input.byteAt(i));
             }
             // TODO: Check that 0 <= code && code <= 0xFF.
-            result[pos++] = (byte)code;
+            result[pos++] = (byte) code;
           } else {
             switch (c) {
               case 'a' : result[pos++] = 0x07; break;
@@ -1777,12 +1784,12 @@
                   ++i;
                   code = code * 16 + digitValue(input.byteAt(i));
                 }
-                result[pos++] = (byte)code;
+                result[pos++] = (byte) code;
                 break;
 
               default:
                 throw new InvalidEscapeSequenceException(
-                    "Invalid escape sequence: '\\" + (char)c + '\'');
+                    "Invalid escape sequence: '\\" + (char) c + '\'');
             }
           }
         } else {
@@ -1841,9 +1848,9 @@
 
   /** Is this a hex digit? */
   private static boolean isHex(final byte c) {
-    return ('0' <= c && c <= '9') ||
-           ('a' <= c && c <= 'f') ||
-           ('A' <= c && c <= 'F');
+    return ('0' <= c && c <= '9')
+        || ('a' <= c && c <= 'f')
+        || ('A' <= c && c <= 'F');
   }
 
   /**
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index eba2528..ba83b66 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -30,6 +30,8 @@
 
 package com.google.protobuf;
 
+import java.io.IOException;
+
 /**
  * This class is used internally by the Protocol Buffer library and generated
  * message implementations.  It is public only because those generated messages
@@ -160,4 +162,84 @@
     makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
   static final int MESSAGE_SET_MESSAGE_TAG =
     makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
+
+  /**
+   * Validation level for handling incoming string field data which potentially
+   * contain non-UTF8 bytes.
+   */
+  enum Utf8Validation {
+    /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */
+    LOOSE {
+      Object readString(CodedInputStream input) throws IOException {
+        return input.readString();
+      }
+    },
+    /** Eagerly parses to String; throws an IOException on invalid bytes. */
+    STRICT {
+      Object readString(CodedInputStream input) throws IOException {
+        return input.readStringRequireUtf8();
+      }
+    },
+    /** Keep data as ByteString; validation/conversion to String is lazy. */
+    LAZY {
+      Object readString(CodedInputStream input) throws IOException {
+        return input.readBytes();
+      }
+    };
+
+    /** Read a string field from the input with the proper UTF8 validation. */
+    abstract Object readString(CodedInputStream input) throws IOException;
+  }
+
+  /**
+   * Read a field of any primitive type for immutable messages from a
+   * CodedInputStream. Enums, groups, and embedded messages are not handled by
+   * this method.
+   *
+   * @param input The stream from which to read.
+   * @param type Declared type of the field.
+   * @param utf8Validation Different string UTF8 validation level for handling
+   *                       string fields.
+   * @return An object representing the field's value, of the exact
+   *         type which would be returned by
+   *         {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *         this field.
+   */
+  static Object readPrimitiveField(
+      CodedInputStream input,
+      FieldType type,
+      Utf8Validation utf8Validation) throws IOException {
+    switch (type) {
+      case DOUBLE  : return input.readDouble  ();
+      case FLOAT   : return input.readFloat   ();
+      case INT64   : return input.readInt64   ();
+      case UINT64  : return input.readUInt64  ();
+      case INT32   : return input.readInt32   ();
+      case FIXED64 : return input.readFixed64 ();
+      case FIXED32 : return input.readFixed32 ();
+      case BOOL    : return input.readBool    ();
+      case BYTES   : return input.readBytes   ();
+      case UINT32  : return input.readUInt32  ();
+      case SFIXED32: return input.readSFixed32();
+      case SFIXED64: return input.readSFixed64();
+      case SINT32  : return input.readSInt32  ();
+      case SINT64  : return input.readSInt64  ();
+
+      case STRING  : return utf8Validation.readString(input);
+      case GROUP:
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle nested groups.");
+      case MESSAGE:
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle embedded messages.");
+      case ENUM:
+        // We don't handle enums because we don't know what to do if the
+        // value is not recognized.
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle enums.");
+    }
+
+    throw new RuntimeException(
+      "There is no way to get here, but the compiler thinks otherwise.");
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 41ed7bd..2bd8d1a 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -56,6 +56,7 @@
 import protobuf_unittest.UnittestProto.ForeignEnum;
 import protobuf_unittest.UnittestProto.ForeignMessage;
 import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
@@ -1510,6 +1511,17 @@
     }
   }
 
+  public void testOneofNestedBuilderOnChangePropagation() {
+    NestedTestAllTypes.Builder parentBuilder = NestedTestAllTypes.newBuilder();
+    TestAllTypes.Builder builder = parentBuilder.getPayloadBuilder();
+    builder.getOneofNestedMessageBuilder();
+    assertTrue(builder.hasOneofNestedMessage());
+    assertTrue(parentBuilder.hasPayload());
+    NestedTestAllTypes message = parentBuilder.build();
+    assertTrue(message.hasPayload());
+    assertTrue(message.getPayload().hasOneofNestedMessage());
+  }
+
   public void testGetRepeatedFieldBuilder() {
     Descriptor descriptor = TestAllTypes.getDescriptor();
 
diff --git a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
index e67c6d2..211b569 100644
--- a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
@@ -30,6 +30,9 @@
 
 package com.google.protobuf;
 
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 
@@ -111,12 +114,146 @@
     assertNotEqual(message.toByteString(), lazyField.toByteString());
   }
 
+  public void testMergeExtensions() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyFieldLite original = createLazyFieldLiteFromMessage(message);
+    LazyFieldLite merged = new LazyFieldLite();
+    merged.merge(original);
+    TestAllExtensions value = (TestAllExtensions) merged.getValue(
+        TestAllExtensions.getDefaultInstance());
+    assertEquals(message, value);
+  }
+
+  public void testEmptyLazyField() throws Exception {
+    LazyFieldLite field = new LazyFieldLite();
+    assertEquals(0, field.getSerializedSize());
+    assertEquals(ByteString.EMPTY, field.toByteString());
+  }
+
+  public void testInvalidProto() throws Exception {
+    // Silently fails and uses the default instance.
+    LazyFieldLite field = new LazyFieldLite(
+        TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+    assertEquals(
+        TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance()));
+    assertEquals(0, field.getSerializedSize());
+    assertEquals(ByteString.EMPTY, field.toByteString());
+  }
+
+  public void testMergeBeforeParsing() throws Exception {
+    TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+    LazyFieldLite field1 = createLazyFieldLiteFromMessage(message1);
+    TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+    LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+
+    field1.merge(field2);
+    TestAllTypes expected =
+        TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+    assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testMergeOneNotParsed() throws Exception {
+    // Test a few different paths that involve one message that was not parsed.
+    TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+    TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+    TestAllTypes expected =
+        TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+
+    LazyFieldLite field1 = LazyFieldLite.fromValue(message1);
+    field1.getValue(TestAllTypes.getDefaultInstance());  // Force parsing.
+    LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+    field1.merge(field2);
+    assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+
+    // Now reverse which one is parsed first.
+    field1 = LazyFieldLite.fromValue(message1);
+    field2 = createLazyFieldLiteFromMessage(message2);
+    field2.getValue(TestAllTypes.getDefaultInstance());  // Force parsing.
+    field1.merge(field2);
+    assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testMergeInvalid() throws Exception {
+    // Test a few different paths that involve one message that was not parsed.
+    TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+    LazyFieldLite valid = LazyFieldLite.fromValue(message);
+    LazyFieldLite invalid = new LazyFieldLite(
+        TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+    invalid.merge(valid);
+
+    // We swallow the exception and just use the set field.
+    assertEquals(message, invalid.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testMergeKeepsExtensionsWhenPossible() throws Exception {
+    // In this test we attempt to only use the empty registry, which will strip out all extensions
+    // when serializing and then parsing. We verify that each code path will attempt to not
+    // serialize and parse a message that was set directly without going through the
+    // extensionRegistry.
+    TestAllExtensions messageWithExtensions =
+        TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 42).build();
+    TestAllExtensions emptyMessage = TestAllExtensions.newBuilder().build();
+
+    ExtensionRegistryLite emptyRegistry = ExtensionRegistryLite.getEmptyRegistry();
+
+    LazyFieldLite field = LazyFieldLite.fromValue(messageWithExtensions);
+    field.merge(createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage));
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+    // Now reverse the order of the merging.
+    field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+    field.merge(LazyFieldLite.fromValue(messageWithExtensions));
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+    // Now try parsing the empty field first.
+    field = LazyFieldLite.fromValue(messageWithExtensions);
+    LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+    other.getValue(TestAllExtensions.getDefaultInstance());  // Force parsing.
+    field.merge(other);
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+    // And again reverse.
+    field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+    field.getValue(TestAllExtensions.getDefaultInstance());  // Force parsing.
+    other = LazyFieldLite.fromValue(messageWithExtensions);
+    field.merge(other);
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+  }
+
+  public void testMergeMightLoseExtensions() throws Exception {
+    // Test that we don't know about the extensions when parsing.
+    TestAllExtensions message1 =
+        TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 1).build();
+    TestAllExtensions message2 =
+        TestAllExtensions.newBuilder().setExtension(optionalInt64Extension, 2L).build();
+
+    LazyFieldLite field = LazyFieldLite.fromValue(message1);
+    field.merge(LazyFieldLite.fromValue(message2));
+
+    // We lose the extensions from message 2 because we have to serialize it and then parse it
+    // again, using the empty registry this time.
+    TestAllExtensions value =
+        (TestAllExtensions) field.getValue(TestAllExtensions.getDefaultInstance());
+    assertTrue(value.hasExtension(optionalInt32Extension));
+    assertEquals(Integer.valueOf(1), value.getExtension(optionalInt32Extension));
+    assertFalse(value.hasExtension(optionalInt64Extension));
+
+    // The field is still there, it is just unknown.
+    assertTrue(value.getUnknownFields()
+        .hasField(optionalInt64Extension.getDescriptor().getNumber()));
+  }
+
 
   // Help methods.
 
   private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) {
+    return createLazyFieldLiteFromMessage(TestUtil.getExtensionRegistry(), message);
+  }
+
+  private LazyFieldLite createLazyFieldLiteFromMessage(
+      ExtensionRegistryLite extensionRegistry, MessageLite message) {
     ByteString bytes = message.toByteString();
-    return new LazyFieldLite(TestUtil.getExtensionRegistry(), bytes);
+    return new LazyFieldLite(extensionRegistry, bytes);
   }
 
   private void changeValue(LazyFieldLite lazyField) {
diff --git a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
index 9de794f..afe0fff 100644
--- a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import protobuf_unittest.LazyFieldsLite.LazyExtension;
 import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite;
 import protobuf_unittest.LazyFieldsLite.LazyMessageLite;
 import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite;
@@ -285,4 +286,22 @@
 
     assertEquals(bytes, deserialized.toByteString());
   }
+
+  public void testExtensions() throws Exception {
+    LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder();
+    innerBuilder.setExtension(
+        LazyExtension.extension, LazyExtension.newBuilder()
+        .setName("name").build());
+    assertTrue(innerBuilder.hasExtension(LazyExtension.extension));
+    assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName());
+
+    LazyInnerMessageLite innerMessage = innerBuilder.build();
+    assertTrue(innerMessage.hasExtension(LazyExtension.extension));
+    assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName());
+
+    LazyMessageLite lite = LazyMessageLite.newBuilder()
+        .setInner(innerMessage).build();
+    assertTrue(lite.getInner().hasExtension(LazyExtension.extension));
+    assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName());
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index ff39ca3..046832d 100644
--- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -289,7 +289,6 @@
     assertEquals("Output.reset() resets the output", 0, output.size());
     assertEquals("Output.reset() resets the output",
         ByteString.EMPTY, output.toByteString());
-    
   }
 
   public void testToString() throws UnsupportedEncodingException {
@@ -299,6 +298,27 @@
     assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
   }
 
+  public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{
+    assertSame(classUnderTest + " must be the same string references",
+        ByteString.EMPTY.toString(UTF_8), new LiteralByteString(new byte[]{}).toString(UTF_8));
+  }
+
+  public void testToString_raisesException() throws UnsupportedEncodingException{
+    try {
+      ByteString.EMPTY.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+
+    try {
+      new LiteralByteString(referenceBytes).toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+  }
+
   public void testEquals() {
     assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
     assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
@@ -311,7 +331,7 @@
 
     byte[] mungedBytes = new byte[referenceBytes.length];
     System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
-    mungedBytes[mungedBytes.length - 5] ^= 0xFF;
+    mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
     assertFalse(classUnderTest + " must not equal every string with the same length",
         stringUnderTest.equals(new LiteralByteString(mungedBytes)));
   }
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
index 33ba715..78cba1b 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -34,6 +34,7 @@
 import map_test.MapForProto2TestProto.TestMap;
 import map_test.MapForProto2TestProto.TestMap.MessageValue;
 import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
+import map_test.MapForProto2TestProto.TestRecursiveMap;
 import map_test.MapForProto2TestProto.TestUnknownEnumValue;
 
 import junit.framework.TestCase;
@@ -499,4 +500,17 @@
     message = builder.build();
     assertTrue(message.isInitialized());
   }
+
+  public void testRecursiveMap() throws Exception {
+    TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder();
+    builder.getMutableRecursiveMapField().put(
+        1, TestRecursiveMap.newBuilder().setValue(2).build());
+    builder.getMutableRecursiveMapField().put(
+        3, TestRecursiveMap.newBuilder().setValue(4).build());
+    ByteString data = builder.build().toByteString();
+
+    TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
+    assertEquals(2, message.getRecursiveMapField().get(1).getValue());
+    assertEquals(4, message.getRecursiveMapField().get(3).getValue());
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
index 9a25e30..b8e67b7 100644
--- a/java/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -57,22 +57,22 @@
     builder.getMutableInt32ToStringField().put(1, "11");
     builder.getMutableInt32ToStringField().put(2, "22");
     builder.getMutableInt32ToStringField().put(3, "33");
-    
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
     builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
     builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
-    
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
-    
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(11).build());
     builder.getMutableInt32ToMessageField().put(
         2, MessageValue.newBuilder().setValue(22).build());
     builder.getMutableInt32ToMessageField().put(
         3, MessageValue.newBuilder().setValue(33).build());
-    
+
     builder.getMutableStringToInt32Field().put("1", 11);
     builder.getMutableStringToInt32Field().put("2", 22);
     builder.getMutableStringToInt32Field().put("3", 33);
@@ -88,22 +88,22 @@
     assertEquals("11", message.getInt32ToStringField().get(1));
     assertEquals("22", message.getInt32ToStringField().get(2));
     assertEquals("33", message.getInt32ToStringField().get(3));
-    
+
     assertEquals(3, message.getInt32ToBytesField().size());
     assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
     assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-    
+
     assertEquals(3, message.getInt32ToEnumField().size());
     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-    
+
     assertEquals(3, message.getInt32ToMessageField().size());
     assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
     assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
     assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-    
+
     assertEquals(3, message.getStringToInt32Field().size());
     assertEquals(11, message.getStringToInt32Field().get("1").intValue());
     assertEquals(22, message.getStringToInt32Field().get("2").intValue());
@@ -118,21 +118,21 @@
     builder.getMutableInt32ToStringField().put(1, "111");
     builder.getMutableInt32ToStringField().remove(2);
     builder.getMutableInt32ToStringField().put(4, "44");
-    
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
     builder.getMutableInt32ToBytesField().remove(2);
     builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
-    
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().remove(2);
     builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
-    
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(111).build());
     builder.getMutableInt32ToMessageField().remove(2);
     builder.getMutableInt32ToMessageField().put(
         4, MessageValue.newBuilder().setValue(44).build());
-    
+
     builder.getMutableStringToInt32Field().put("1", 111);
     builder.getMutableStringToInt32Field().remove("2");
     builder.getMutableStringToInt32Field().put("4", 44);
@@ -148,22 +148,22 @@
     assertEquals("111", message.getInt32ToStringField().get(1));
     assertEquals("33", message.getInt32ToStringField().get(3));
     assertEquals("44", message.getInt32ToStringField().get(4));
-    
+
     assertEquals(3, message.getInt32ToBytesField().size());
     assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
     assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
-    
+
     assertEquals(3, message.getInt32ToEnumField().size());
     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
     assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
-    
+
     assertEquals(3, message.getInt32ToMessageField().size());
     assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
     assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
     assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
-    
+
     assertEquals(3, message.getStringToInt32Field().size());
     assertEquals(111, message.getStringToInt32Field().get("1").intValue());
     assertEquals(33, message.getStringToInt32Field().get("3").intValue());
@@ -183,17 +183,17 @@
     TestMap.Builder builder = TestMap.newBuilder();
     TestMap message = builder.build();
     assertMapValuesCleared(message);
-    
+
     builder = message.toBuilder();
     setMapValues(builder);
     message = builder.build();
     assertMapValuesSet(message);
-    
+
     builder = message.toBuilder();
     updateMapValues(builder);
     message = builder.build();
     assertMapValuesUpdated(message);
-    
+
     builder = message.toBuilder();
     builder.clear();
     message = builder.build();
@@ -207,14 +207,14 @@
     assertEquals(message.getSerializedSize(), message.toByteString().size());
     message = TestMap.PARSER.parseFrom(message.toByteString());
     assertMapValuesSet(message);
-    
+
     builder = message.toBuilder();
     updateMapValues(builder);
     message = builder.build();
     assertEquals(message.getSerializedSize(), message.toByteString().size());
     message = TestMap.PARSER.parseFrom(message.toByteString());
     assertMapValuesUpdated(message);
-    
+
     builder = message.toBuilder();
     builder.clear();
     message = builder.build();
@@ -222,12 +222,12 @@
     message = TestMap.PARSER.parseFrom(message.toByteString());
     assertMapValuesCleared(message);
   }
-  
+
   public void testMergeFrom() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    
+
     TestMap.Builder other = TestMap.newBuilder();
     other.mergeFrom(message);
     assertMapValuesSet(other.build());
@@ -236,7 +236,7 @@
   public void testEqualsAndHashCode() throws Exception {
     // Test that generated equals() and hashCode() will disregard the order
     // of map entries when comparing/hashing map fields.
-    
+
     // We can't control the order of elements in a HashMap. The best we can do
     // here is to add elements in different order.
     TestMap.Builder b1 = TestMap.newBuilder();
@@ -244,23 +244,23 @@
     b1.getMutableInt32ToInt32Field().put(3, 4);
     b1.getMutableInt32ToInt32Field().put(5, 6);
     TestMap m1 = b1.build();
-    
+
     TestMap.Builder b2 = TestMap.newBuilder();
     b2.getMutableInt32ToInt32Field().put(5, 6);
     b2.getMutableInt32ToInt32Field().put(1, 2);
     b2.getMutableInt32ToInt32Field().put(3, 4);
     TestMap m2 = b2.build();
-    
+
     assertEquals(m1, m2);
     assertEquals(m1.hashCode(), m2.hashCode());
-    
+
     // Make sure we did compare map fields.
     b2.getMutableInt32ToInt32Field().put(1, 0);
     m2 = b2.build();
     assertFalse(m1.equals(m2));
     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
     // to be different.
-    
+
     // Regression test for b/18549190: if a map is a subset of the other map,
     // equals() should return false.
     b2.getMutableInt32ToInt32Field().remove(1);
@@ -268,57 +268,95 @@
     assertFalse(m1.equals(m2));
     assertFalse(m2.equals(m1));
   }
-  
-  
+
   public void testNestedBuilderOnChangeEventPropagation() {
     TestOnChangeEventPropagation.Builder parent =
         TestOnChangeEventPropagation.newBuilder();
     parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
     TestOnChangeEventPropagation message = parent.build();
     assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-    
+
     // Make a change using nested builder.
     parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
-    
+
     // Should be able to observe the change.
     message = parent.build();
     assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-    
+
     // Make another change using mergeFrom()
     TestMap.Builder other = TestMap.newBuilder();
     other.getMutableInt32ToInt32Field().put(1, 4);
     parent.getOptionalMessageBuilder().mergeFrom(other.build());
-    
+
     // Should be able to observe the change.
     message = parent.build();
     assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-    
+
     // Make yet another change by clearing the nested builder.
     parent.getOptionalMessageBuilder().clear();
-    
+
     // Should be able to observe the change.
     message = parent.build();
     assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
   }
-  
+
+  public void testNestedBuilderOnChangeEventPropagationReflection() {
+    FieldDescriptor intMapField = f("int32_to_int32_field");
+    // Create an outer message builder with nested builder.
+    TestOnChangeEventPropagation.Builder parentBuilder =
+        TestOnChangeEventPropagation.newBuilder();
+    TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+
+    // Create a map entry message.
+    TestMap.Builder entryBuilder = TestMap.newBuilder();
+    entryBuilder.getMutableInt32ToInt32Field().put(1, 1);
+
+    // Put the entry into the nested builder.
+    testMapBuilder.addRepeatedField(
+        intMapField, entryBuilder.getRepeatedField(intMapField, 0));
+
+    // Should be able to observe the change.
+    TestOnChangeEventPropagation message = parentBuilder.build();
+    assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+
+    // Change the entry value.
+    entryBuilder.getMutableInt32ToInt32Field().put(1, 4);
+    testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+    testMapBuilder.setRepeatedField(
+        intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
+
+    // Should be able to observe the change.
+    message = parentBuilder.build();
+    assertEquals(4,
+        message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+    // Clear the nested builder.
+    testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+    testMapBuilder.clearField(intMapField);
+
+    // Should be able to observe the change.
+    message = parentBuilder.build();
+    assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+  }
+
   // The following methods are used to test reflection API.
-  
+
   private static FieldDescriptor f(String name) {
     return TestMap.getDescriptor().findFieldByName(name);
   }
-  
+
   private static Object getFieldValue(Message mapEntry, String name) {
     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
     return mapEntry.getField(field);
   }
-  
+
   private static Message.Builder setFieldValue(
       Message.Builder mapEntry, String name, Object value) {
     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
     mapEntry.setField(field, value);
     return mapEntry;
   }
-  
+
   private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
     FieldDescriptor field = f(name);
     for (Object entry : (List<?>) message.getField(field)) {
@@ -337,7 +375,7 @@
       assertEquals(value, values.get(key));
     }
   }
-  
+
   private static <KeyType, ValueType>
   Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
@@ -348,7 +386,7 @@
     entryBuilder.setField(valueField, value);
     return entryBuilder.build();
   }
-  
+
   private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
     List<Message> entryList = new ArrayList<Message>();
     for (Map.Entry<?, ?> entry : values.entrySet()) {
@@ -357,7 +395,7 @@
     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
     builder.setField(field, entryList);
   }
-  
+
   private static <KeyType, ValueType>
   Map<KeyType, ValueType> mapForValues(
       KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
@@ -385,14 +423,14 @@
         mapForValues(
             11, MessageValue.newBuilder().setValue(22).build(),
             33, MessageValue.newBuilder().setValue(44).build()));
-    
+
     // Test clearField()
     builder.clearField(f("int32_to_int32_field"));
     builder.clearField(f("int32_to_message_field"));
     message = builder.build();
     assertEquals(0, message.getInt32ToInt32Field().size());
     assertEquals(0, message.getInt32ToMessageField().size());
-    
+
     // Test setField()
     setMapValues(builder, "int32_to_int32_field",
         mapForValues(11, 22, 33, 44));
@@ -405,7 +443,7 @@
     assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
     assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
     assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
-    
+
     // Test addRepeatedField
     builder.addRepeatedField(f("int32_to_int32_field"),
         newMapEntry(builder, "int32_to_int32_field", 55, 66));
@@ -425,7 +463,7 @@
     message = builder.build();
     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
     assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
-    
+
     // Test setRepeatedField
     for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
       Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
@@ -442,35 +480,35 @@
     assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
   }
-  
+
   public void testTextFormat() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    
+
     String textData = TextFormat.printToString(message);
-    
+
     builder = TestMap.newBuilder();
     TextFormat.merge(textData, builder);
     message = builder.build();
-    
+
     assertMapValuesSet(message);
   }
-  
+
   public void testDynamicMessage() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    
+
     Message dynamicDefaultInstance =
         DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
     Message dynamicMessage = dynamicDefaultInstance
         .newBuilderForType().mergeFrom(message.toByteString()).build();
-    
+
     assertEquals(message, dynamicMessage);
     assertEquals(message.hashCode(), dynamicMessage.hashCode());
   }
-  
+
   public void testReflectionEqualsAndHashCode() throws Exception {
     // Test that generated equals() and hashCode() will disregard the order
     // of map entries when comparing/hashing map fields.
@@ -479,22 +517,22 @@
     Message dynamicDefaultInstance =
         DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
     FieldDescriptor field = f("int32_to_int32_field");
-    
+
     Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
     Message m1 = b1.build();
-    
+
     Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
     Message m2 = b2.build();
-    
+
     assertEquals(m1, m2);
     assertEquals(m1.hashCode(), m2.hashCode());
-    
+
     // Make sure we did compare map fields.
     b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
     m2 = b2.build();
@@ -502,7 +540,7 @@
     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
     // to be different.
   }
-  
+
   public void testUnknownEnumValues() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     builder.getMutableInt32ToEnumFieldValue().put(0, 0);
@@ -517,7 +555,7 @@
     assertEquals(TestMap.EnumValue.UNRECOGNIZED,
         message.getInt32ToEnumField().get(2));
     assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
-    
+
     // Unknown enum values should be preserved after:
     //   1. Serialization and parsing.
     //   2. toBuild().
@@ -528,7 +566,7 @@
     assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
     builder = TestMap.newBuilder().mergeFrom(message);
     assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
-    
+
     // hashCode()/equals() should take unknown enum values into account.
     builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
     TestMap message2 = builder.build();
@@ -538,17 +576,17 @@
     // should be the same.
     assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
   }
-  
+
   public void testUnknownEnumValuesInReflectionApi() throws Exception {
     Descriptor descriptor = TestMap.getDescriptor();
     EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
     FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
-    
+
     Map<Integer, Integer> data = new HashMap<Integer, Integer>();
     data.put(0, 0);
     data.put(1, 1);
     data.put(2, 1000);  // unknown value.
-    
+
     TestMap.Builder builder = TestMap.newBuilder();
     for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
       builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());
diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
index b397019..0f2344d 100644
--- a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -118,6 +118,34 @@
         flatString.hashCode(), unicode.hashCode());
   }
 
+  @Override
+  public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException {
+    RopeByteString ropeByteString =
+        RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+    assertSame(classUnderTest + " must be the same string references",
+        ByteString.EMPTY.toString(UTF_8), ropeByteString.toString(UTF_8));
+  }
+
+  public void testToString_raisesException() throws UnsupportedEncodingException{
+    try {
+      ByteString byteString =
+          RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+      byteString.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+
+    try {
+      ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"),
+          ByteString.copyFromUtf8("bar"));
+      byteString.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+  }
+
   public void testJavaSerialization() throws Exception {
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     ObjectOutputStream oos = new ObjectOutputStream(out);
diff --git a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
index 015dc26..5580f72 100644
--- a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
+++ b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
@@ -54,6 +54,15 @@
   optional int32 num = 1;
   optional int32 num_with_default = 2 [default = 42];
   optional LazyNestedInnerMessageLite nested = 3 [lazy = true];
+
+  extensions 1000 to max;
+}
+
+message LazyExtension {
+  extend LazyInnerMessageLite {
+    optional LazyExtension extension = 1000;
+  }
+  optional string name = 1;
 }
 
 message LazyNestedInnerMessageLite {
diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
index a1fe856..d5418f2 100644
--- a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
@@ -63,6 +63,13 @@
   // parsing behavior of TestMap regarding unknown enum values.
   map<int32, int32> int32_to_int32_field = 4;
 }
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+  optional int32 value = 1;
+  map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
 package map_for_proto2_lite_test;
 option java_package = "map_lite_test";
 option optimize_for = LITE_RUNTIME;
diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
index a0ec7ac..a9be516 100644
--- a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
@@ -65,3 +65,10 @@
   // parsing behavior of TestMap regarding unknown enum values.
   map<int32, int32> int32_to_int32_field = 4;
 }
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+  optional int32 value = 1;
+  map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
diff --git a/java/src/test/java/com/google/protobuf/map_test.proto b/java/src/test/java/com/google/protobuf/map_test.proto
index 105ee3f..bf692c2 100644
--- a/java/src/test/java/com/google/protobuf/map_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_test.proto
@@ -36,6 +36,7 @@
 option java_outer_classname = "MapTestProto";
 option java_generate_equals_and_hash = true;
 
+
 message TestMap {
   message MessageValue {
     optional int32 value = 1;
diff --git a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
index 67035fd..dc08261 100644
--- a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
+++ b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
@@ -45,6 +45,7 @@
 option java_outer_classname = "TestBadIdentifiersProto";
 option java_generate_equals_and_hash = true;
 
+
 message TestMessage {
   optional string cached_size = 1;
   optional string serialized_size = 2;
diff --git a/javanano/README.txt b/javanano/README.txt
index 5a05b86..cfb3c3b 100644
--- a/javanano/README.txt
+++ b/javanano/README.txt
@@ -68,18 +68,20 @@
 Nano version
 ============================
 
-Nano is a special code generator and runtime library designed specially
-for Android, and is very resource-friendly in both the amount of code
-and the runtime overhead. An overview of Nano features:
+JavaNano is a special code generator and runtime library designed specially for
+resource-restricted systems, like Android. It is very resource-friendly in both
+the amount of code and the runtime overhead. Here is 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.
-- If not opted in, has state is not available. Serialization outputs
-  all fields not equal to their defaults (see important implications
-  below).
-- Required fields are always serialized.
+- For proto2, if not opted in, has state (field presence) is not available.
+  Serialization outputs all fields not equal to their defaults
+  (see important implications below).
+  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
@@ -88,8 +90,8 @@
 - 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 of serializing/deserializing repeated packed fields.
-- Support of extensions.
+- 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
@@ -200,7 +202,7 @@
 
   In the default style, optional fields translate into public mutable
   Java fields, and the serialization process is as discussed in the
-  "IMPORTANT" section above. 
+  "IMPORTANT" section above.
 
   * accessors *
 
diff --git a/javanano/pom.xml b/javanano/pom.xml
index 3d98a5e..7a2be9d 100644
--- a/javanano/pom.xml
+++ b/javanano/pom.xml
@@ -10,7 +10,7 @@
   </parent>
   <groupId>com.google.protobuf.nano</groupId>
   <artifactId>protobuf-javanano</artifactId>
-  <version>2.6.2-pre</version>
+  <version>3.0.0-alpha-3-pre</version>
   <packaging>bundle</packaging>
   <name>Protocol Buffer JavaNano API</name>
   <description>
@@ -94,6 +94,7 @@
                   <arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto" />
                   <arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
                   <arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/map_test.proto" />
                 </exec>
                 <exec executable="../src/protoc">
                   <arg value="--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources" />
@@ -155,10 +156,70 @@
           <instructions>
             <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
             <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
-            <Export-Package>com.google.protobuf;version=2.6.2-pre</Export-Package>
+            <Export-Package>com.google.protobuf;version=3.0.0-alpha-3-pre</Export-Package>
           </instructions>
         </configuration>
       </plugin>
     </plugins>
   </build>
+  <profiles>
+    <profile>
+      <id>release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <version>2.2.1</version>
+            <executions>
+              <execution>
+                <id>attach-sources</id>
+                <goals>
+                  <goal>jar-no-fork</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.9.1</version>
+            <executions>
+              <execution>
+                <id>attach-javadocs</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.5</version>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>nexus-staging-maven-plugin</artifactId>
+            <version>1.6.3</version>
+            <extensions>true</extensions>
+            <configuration>
+               <serverId>sonatype-nexus-staging</serverId>
+               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+               <autoReleaseAfterClose>false</autoReleaseAfterClose>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 </project>
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
index b147f69..b4f20fd 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
@@ -638,4 +638,44 @@
       throw InvalidProtocolBufferNanoException.truncatedMessage();
     }
   }
+
+  // Read a primitive type.
+  Object readPrimitiveField(int type) throws IOException {
+    switch (type) {
+      case InternalNano.TYPE_DOUBLE:
+          return readDouble();
+      case InternalNano.TYPE_FLOAT:
+          return readFloat();
+      case InternalNano.TYPE_INT64:
+          return readInt64();
+      case InternalNano.TYPE_UINT64:
+          return readUInt64();
+      case InternalNano.TYPE_INT32:
+          return readInt32();
+      case InternalNano.TYPE_FIXED64:
+          return readFixed64();
+      case InternalNano.TYPE_FIXED32:
+          return readFixed32();
+      case InternalNano.TYPE_BOOL:
+          return readBool();
+      case InternalNano.TYPE_STRING:
+          return readString();
+      case InternalNano.TYPE_BYTES:
+          return readBytes();
+      case InternalNano.TYPE_UINT32:
+          return readUInt32();
+      case InternalNano.TYPE_ENUM:
+          return readEnum();
+      case InternalNano.TYPE_SFIXED32:
+          return readSFixed32();
+      case InternalNano.TYPE_SFIXED64:
+          return readSFixed64();
+      case InternalNano.TYPE_SINT32:
+          return readSInt32();
+      case InternalNano.TYPE_SINT64:
+          return readSInt64();
+      default:
+          throw new IllegalArgumentException("Unknown type " + type);
+    }
+  }
 }
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
index 37982b5..2777f34 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
@@ -876,4 +876,128 @@
     // Note:  the right-shift must be arithmetic
     return (n << 1) ^ (n >> 63);
   }
+
+  static int computeFieldSize(int number, int type, Object object) {
+    switch (type) {
+      case InternalNano.TYPE_BOOL:
+        return computeBoolSize(number, (Boolean) object);
+      case InternalNano.TYPE_BYTES:
+        return computeBytesSize(number, (byte[]) object);
+      case InternalNano.TYPE_STRING:
+        return computeStringSize(number, (String) object);
+      case InternalNano.TYPE_FLOAT:
+        return computeFloatSize(number, (Float) object);
+      case InternalNano.TYPE_DOUBLE:
+        return computeDoubleSize(number, (Double) object);
+      case InternalNano.TYPE_ENUM:
+        return computeEnumSize(number, (Integer) object);
+      case InternalNano.TYPE_FIXED32:
+        return computeFixed32Size(number, (Integer) object);
+      case InternalNano.TYPE_INT32:
+        return computeInt32Size(number, (Integer) object);
+      case InternalNano.TYPE_UINT32:
+        return computeUInt32Size(number, (Integer) object);
+      case InternalNano.TYPE_SINT32:
+        return computeSInt32Size(number, (Integer) object);
+      case InternalNano.TYPE_SFIXED32:
+        return computeSFixed32Size(number, (Integer) object);
+      case InternalNano.TYPE_INT64:
+        return computeInt64Size(number, (Long) object);
+      case InternalNano.TYPE_UINT64:
+        return computeUInt64Size(number, (Long) object);
+      case InternalNano.TYPE_SINT64:
+        return computeSInt64Size(number, (Long) object);
+      case InternalNano.TYPE_FIXED64:
+        return computeFixed64Size(number, (Long) object);
+      case InternalNano.TYPE_SFIXED64:
+        return computeSFixed64Size(number, (Long) object);
+      case InternalNano.TYPE_MESSAGE:
+        return computeMessageSize(number, (MessageNano) object);
+      case InternalNano.TYPE_GROUP:
+        return computeGroupSize(number, (MessageNano) object);
+      default:
+        throw new IllegalArgumentException("Unknown type: " + type);
+    }
+  }
+
+  void writeField(int number, int type, Object value)
+      throws IOException {
+    switch (type) {
+      case InternalNano.TYPE_DOUBLE:
+        Double doubleValue = (Double) value;
+        writeDouble(number, doubleValue);
+        break;
+      case InternalNano.TYPE_FLOAT:
+        Float floatValue = (Float) value;
+        writeFloat(number, floatValue);
+        break;
+      case InternalNano.TYPE_INT64:
+        Long int64Value = (Long) value;
+        writeInt64(number, int64Value);
+        break;
+      case InternalNano.TYPE_UINT64:
+        Long uint64Value = (Long) value;
+        writeUInt64(number, uint64Value);
+        break;
+      case InternalNano.TYPE_INT32:
+        Integer int32Value = (Integer) value;
+        writeInt32(number, int32Value);
+        break;
+      case InternalNano.TYPE_FIXED64:
+        Long fixed64Value = (Long) value;
+        writeFixed64(number, fixed64Value);
+        break;
+      case InternalNano.TYPE_FIXED32:
+        Integer fixed32Value = (Integer) value;
+        writeFixed32(number, fixed32Value);
+        break;
+      case InternalNano.TYPE_BOOL:
+        Boolean boolValue = (Boolean) value;
+        writeBool(number, boolValue);
+        break;
+      case InternalNano.TYPE_STRING:
+        String stringValue = (String) value;
+        writeString(number, stringValue);
+        break;
+      case InternalNano.TYPE_BYTES:
+        byte[] bytesValue = (byte[]) value;
+        writeBytes(number, bytesValue);
+        break;
+      case InternalNano.TYPE_UINT32:
+        Integer uint32Value = (Integer) value;
+        writeUInt32(number, uint32Value);
+        break;
+      case InternalNano.TYPE_ENUM:
+        Integer enumValue = (Integer) value;
+        writeEnum(number, enumValue);
+        break;
+      case InternalNano.TYPE_SFIXED32:
+        Integer sfixed32Value = (Integer) value;
+        writeSFixed32(number, sfixed32Value);
+        break;
+      case InternalNano.TYPE_SFIXED64:
+        Long sfixed64Value = (Long) value;
+        writeSFixed64(number, sfixed64Value);
+        break;
+      case InternalNano.TYPE_SINT32:
+        Integer sint32Value = (Integer) value;
+        writeSInt32(number, sint32Value);
+        break;
+      case InternalNano.TYPE_SINT64:
+        Long sint64Value = (Long) value;
+        writeSInt64(number, sint64Value);
+        break;
+      case InternalNano.TYPE_MESSAGE:
+        MessageNano messageValue = (MessageNano) value;
+        writeMessage(number, messageValue);
+        break;
+      case InternalNano.TYPE_GROUP:
+        MessageNano groupValue = (MessageNano) value;
+        writeGroup(number, groupValue);
+        break;
+      default:
+        throw new IOException("Unknown type: " + type);
+    }
+  }
+
 }
diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java
index 5d18ae6..c29b030 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/Extension.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/Extension.java
@@ -55,24 +55,24 @@
      *       PrimitiveExtension      // for primitive/enum typed extensions
      */
 
-    public static final int TYPE_DOUBLE   = 1;
-    public static final int TYPE_FLOAT    = 2;
-    public static final int TYPE_INT64    = 3;
-    public static final int TYPE_UINT64   = 4;
-    public static final int TYPE_INT32    = 5;
-    public static final int TYPE_FIXED64  = 6;
-    public static final int TYPE_FIXED32  = 7;
-    public static final int TYPE_BOOL     = 8;
-    public static final int TYPE_STRING   = 9;
-    public static final int TYPE_GROUP    = 10;
-    public static final int TYPE_MESSAGE  = 11;
-    public static final int TYPE_BYTES    = 12;
-    public static final int TYPE_UINT32   = 13;
-    public static final int TYPE_ENUM     = 14;
-    public static final int TYPE_SFIXED32 = 15;
-    public static final int TYPE_SFIXED64 = 16;
-    public static final int TYPE_SINT32   = 17;
-    public static final int TYPE_SINT64   = 18;
+    public static final int TYPE_DOUBLE   = InternalNano.TYPE_DOUBLE;
+    public static final int TYPE_FLOAT    = InternalNano.TYPE_FLOAT;
+    public static final int TYPE_INT64    = InternalNano.TYPE_INT64;
+    public static final int TYPE_UINT64   = InternalNano.TYPE_UINT64;
+    public static final int TYPE_INT32    = InternalNano.TYPE_INT32;
+    public static final int TYPE_FIXED64  = InternalNano.TYPE_FIXED64;
+    public static final int TYPE_FIXED32  = InternalNano.TYPE_FIXED32;
+    public static final int TYPE_BOOL     = InternalNano.TYPE_BOOL;
+    public static final int TYPE_STRING   = InternalNano.TYPE_STRING;
+    public static final int TYPE_GROUP    = InternalNano.TYPE_GROUP;
+    public static final int TYPE_MESSAGE  = InternalNano.TYPE_MESSAGE;
+    public static final int TYPE_BYTES    = InternalNano.TYPE_BYTES;
+    public static final int TYPE_UINT32   = InternalNano.TYPE_UINT32;
+    public static final int TYPE_ENUM     = InternalNano.TYPE_ENUM;
+    public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32;
+    public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64;
+    public static final int TYPE_SINT32   = InternalNano.TYPE_SINT32;
+    public static final int TYPE_SINT64   = InternalNano.TYPE_SINT64;
 
     /**
      * Creates an {@code Extension} of the given message type and tag number.
@@ -338,42 +338,7 @@
         @Override
         protected Object readData(CodedInputByteBufferNano input) {
             try {
-                switch (type) {
-                    case TYPE_DOUBLE:
-                        return input.readDouble();
-                    case TYPE_FLOAT:
-                        return input.readFloat();
-                    case TYPE_INT64:
-                        return input.readInt64();
-                    case TYPE_UINT64:
-                        return input.readUInt64();
-                    case TYPE_INT32:
-                        return input.readInt32();
-                    case TYPE_FIXED64:
-                        return input.readFixed64();
-                    case TYPE_FIXED32:
-                        return input.readFixed32();
-                    case TYPE_BOOL:
-                        return input.readBool();
-                    case TYPE_STRING:
-                        return input.readString();
-                    case TYPE_BYTES:
-                        return input.readBytes();
-                    case TYPE_UINT32:
-                        return input.readUInt32();
-                    case TYPE_ENUM:
-                        return input.readEnum();
-                    case TYPE_SFIXED32:
-                        return input.readSFixed32();
-                    case TYPE_SFIXED64:
-                        return input.readSFixed64();
-                    case TYPE_SINT32:
-                        return input.readSInt32();
-                    case TYPE_SINT64:
-                        return input.readSInt64();
-                    default:
-                        throw new IllegalArgumentException("Unknown type " + type);
-                }
+              return input.readPrimitiveField(type);
             } catch (IOException e) {
                 throw new IllegalArgumentException("Error reading extension field", e);
             }
diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
index e08bb4b..4a08bb5 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -30,8 +30,13 @@
 
 package com.google.protobuf.nano;
 
+import com.google.protobuf.nano.MapFactories.MapFactory;
+
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
+import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * The classes contained within are used internally by the Protocol Buffer
@@ -43,6 +48,26 @@
  */
 public final class InternalNano {
 
+  public static final int TYPE_DOUBLE   = 1;
+  public static final int TYPE_FLOAT    = 2;
+  public static final int TYPE_INT64    = 3;
+  public static final int TYPE_UINT64   = 4;
+  public static final int TYPE_INT32    = 5;
+  public static final int TYPE_FIXED64  = 6;
+  public static final int TYPE_FIXED32  = 7;
+  public static final int TYPE_BOOL     = 8;
+  public static final int TYPE_STRING   = 9;
+  public static final int TYPE_GROUP    = 10;
+  public static final int TYPE_MESSAGE  = 11;
+  public static final int TYPE_BYTES    = 12;
+  public static final int TYPE_UINT32   = 13;
+  public static final int TYPE_ENUM     = 14;
+  public static final int TYPE_SFIXED32 = 15;
+  public static final int TYPE_SFIXED64 = 16;
+  public static final int TYPE_SINT32   = 17;
+  public static final int TYPE_SINT64   = 18;
+
+
   private InternalNano() {}
 
   /**
@@ -329,5 +354,202 @@
     }
     return result;
   }
+  private static Object primitiveDefaultValue(int type) {
+    switch (type) {
+      case TYPE_BOOL:
+        return Boolean.FALSE;
+      case TYPE_BYTES:
+        return WireFormatNano.EMPTY_BYTES;
+      case TYPE_STRING:
+        return "";
+      case TYPE_FLOAT:
+        return Float.valueOf(0);
+      case TYPE_DOUBLE:
+        return Double.valueOf(0);
+      case TYPE_ENUM:
+      case TYPE_FIXED32:
+      case TYPE_INT32:
+      case TYPE_UINT32:
+      case TYPE_SINT32:
+      case TYPE_SFIXED32:
+        return Integer.valueOf(0);
+      case TYPE_INT64:
+      case TYPE_UINT64:
+      case TYPE_SINT64:
+      case TYPE_FIXED64:
+      case TYPE_SFIXED64:
+        return Long.valueOf(0L);
+      case TYPE_MESSAGE:
+      case TYPE_GROUP:
+      default:
+        throw new IllegalArgumentException(
+            "Type: " + type + " is not a primitive type.");
+    }
+  }
 
+  /**
+   * Merges the map entry into the map field. Note this is only supposed to
+   * be called by generated messages.
+   *
+   * @param map the map field; may be null, in which case a map will be
+   *        instantiated using the {@link MapFactories.MapFactory}
+   * @param input the input byte buffer
+   * @param keyType key type, as defined in InternalNano.TYPE_*
+   * @param valueType value type, as defined in InternalNano.TYPE_*
+   * @param value an new instance of the value, if the value is a TYPE_MESSAGE;
+   *        otherwise this parameter can be null and will be ignored.
+   * @param keyTag wire tag for the key
+   * @param valueTag wire tag for the value
+   * @return the map field
+   * @throws IOException
+   */
+  @SuppressWarnings("unchecked")
+  public static final <K, V> Map<K, V> mergeMapEntry(
+      CodedInputByteBufferNano input,
+      Map<K, V> map,
+      MapFactory mapFactory,
+      int keyType,
+      int valueType,
+      V value,
+      int keyTag,
+      int valueTag) throws IOException {
+    map = mapFactory.forMap(map);
+    final int length = input.readRawVarint32();
+    final int oldLimit = input.pushLimit(length);
+    K key = null;
+    while (true) {
+      int tag = input.readTag();
+      if (tag == 0) {
+        break;
+      }
+      if (tag == keyTag) {
+        key = (K) input.readPrimitiveField(keyType);
+      } else if (tag == valueTag) {
+        if (valueType == TYPE_MESSAGE) {
+          input.readMessage((MessageNano) value);
+        } else {
+          value = (V) input.readPrimitiveField(valueType);
+        }
+      } else {
+        if (!input.skipField(tag)) {
+          break;
+        }
+      }
+    }
+    input.checkLastTagWas(0);
+    input.popLimit(oldLimit);
+
+    if (key == null) {
+      // key can only be primitive types.
+      key = (K) primitiveDefaultValue(keyType);
+    }
+
+    if (value == null) {
+      // message type value will be initialized by code-gen.
+      value = (V) primitiveDefaultValue(valueType);
+    }
+
+    map.put(key, value);
+    return map;
+  }
+
+  public static <K, V> void serializeMapField(
+      CodedOutputByteBufferNano output,
+      Map<K, V> map, int number, int keyType, int valueType)
+          throws IOException {
+    for (Entry<K, V> entry: map.entrySet()) {
+      K key = entry.getKey();
+      V value = entry.getValue();
+      if (key == null || value == null) {
+        throw new IllegalStateException(
+            "keys and values in maps cannot be null");
+      }
+      int entrySize =
+          CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
+          CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
+      output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+      output.writeRawVarint32(entrySize);
+      output.writeField(1, keyType, key);
+      output.writeField(2, valueType, value);
+    }
+  }
+
+  public static <K, V> int computeMapFieldSize(
+      Map<K, V> map, int number, int keyType, int valueType) {
+    int size = 0;
+    int tagSize = CodedOutputByteBufferNano.computeTagSize(number);
+    for (Entry<K, V> entry: map.entrySet()) {
+      K key = entry.getKey();
+      V value = entry.getValue();
+      if (key == null || value == null) {
+        throw new IllegalStateException(
+            "keys and values in maps cannot be null");
+      }
+      int entrySize =
+          CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
+          CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
+      size += tagSize + entrySize
+          + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize);
+    }
+    return size;
+  }
+
+  /**
+   * Checks whether two {@link Map} are equal. We don't use the default equals
+   * method of {@link Map} because it compares by identity not by content for
+   * byte arrays.
+   */
+  public static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
+    if (a == b) {
+      return true;
+    }
+    if (a == null) {
+      return b.size() == 0;
+    }
+    if (b == null) {
+      return a.size() == 0;
+    }
+    if (a.size() != b.size()) {
+      return false;
+    }
+    for (Entry<K, V> entry : a.entrySet()) {
+      if (!b.containsKey(entry.getKey())) {
+        return false;
+      }
+      if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private static boolean equalsMapValue(Object a, Object b) {
+    if (a == null || b == null) {
+      throw new IllegalStateException(
+          "keys and values in maps cannot be null");
+    }
+    if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[]) a, (byte[]) b);
+    }
+    return a.equals(b);
+  }
+
+  public static <K, V> int hashCode(Map<K, V> map) {
+    if (map == null) {
+      return 0;
+    }
+    int result = 0;
+    for (Entry<K, V> entry : map.entrySet()) {
+      result += hashCodeForMap(entry.getKey())
+          ^ hashCodeForMap(entry.getValue());
+    }
+    return result;
+  }
+
+  private static int hashCodeForMap(Object o) {
+    if (o instanceof byte[]) {
+      return Arrays.hashCode((byte[]) o);
+    }
+    return o.hashCode();
+  }
 }
diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
new file mode 100644
index 0000000..98fa487
--- /dev/null
+++ b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for maps support.
+ */
+public final class MapFactories {
+  public static interface MapFactory {
+    <K, V> Map<K, V> forMap(Map<K, V> oldMap);
+  }
+
+  // NOTE(liujisi): The factory setter is temporarily marked as package private.
+  // The way to provide customized implementations of maps for different
+  // platforms are still under discussion.  Mark it as private to avoid exposing
+  // the API in proto3 alpha release.
+  /* public */ static void setMapFactory(MapFactory newMapFactory) {
+    mapFactory = newMapFactory;
+  }
+
+  public static MapFactory getMapFactory() {
+    return mapFactory;
+  }
+
+  private static class DefaultMapFactory implements MapFactory {
+    public <K, V> Map<K, V> forMap(Map<K, V> oldMap) {
+      if (oldMap == null) {
+        return new HashMap<K, V>();
+      }
+      return oldMap;
+    }
+  }
+  private static volatile MapFactory mapFactory = new DefaultMapFactory();
+
+  private MapFactories() {}
+}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
index dd43cdb..c4b2ad3 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
@@ -35,6 +35,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.Map;
 
 /**
  * Static helper methods for printing nano protos.
@@ -170,6 +171,19 @@
                 indentBuf.setLength(origIndentBufLength);
                 buf.append(indentBuf).append(">\n");
             }
+        } else if (object instanceof Map) {
+          Map<?,?> map = (Map<?,?>) object;
+          identifier = deCamelCaseify(identifier);
+
+          for (Map.Entry<?,?> entry : map.entrySet()) {
+            buf.append(indentBuf).append(identifier).append(" <\n");
+            int origIndentBufLength = indentBuf.length();
+            indentBuf.append(INDENT);
+            print("key", entry.getKey(), indentBuf, buf);
+            print("value", entry.getValue(), indentBuf, buf);
+            indentBuf.setLength(origIndentBufLength);
+            buf.append(indentBuf).append(">\n");
+          }
         } else {
             // Non-null primitive value
             identifier = deCamelCaseify(identifier);
diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
index 442f0b7..4cc7722 100644
--- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
+++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
@@ -30,31 +30,11 @@
 
 package com.google.protobuf.nano;
 
-import com.google.protobuf.nano.CodedInputByteBufferNano;
-import com.google.protobuf.nano.EnumClassNanoMultiple;
-import com.google.protobuf.nano.EnumClassNanos;
-import com.google.protobuf.nano.EnumValidity;
-import com.google.protobuf.nano.EnumValidityAccessors;
-import com.google.protobuf.nano.FileScopeEnumMultiple;
-import com.google.protobuf.nano.FileScopeEnumRefNano;
-import com.google.protobuf.nano.InternalNano;
-import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
-import com.google.protobuf.nano.MessageNano;
-import com.google.protobuf.nano.MessageScopeEnumRefNano;
-import com.google.protobuf.nano.MultipleImportingNonMultipleNano1;
-import com.google.protobuf.nano.MultipleImportingNonMultipleNano2;
-import com.google.protobuf.nano.MultipleNameClashNano;
+import com.google.protobuf.nano.MapTestProto.TestMap;
+import com.google.protobuf.nano.MapTestProto.TestMap.MessageValue;
 import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors;
 import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas;
-import com.google.protobuf.nano.NanoOuterClass;
 import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
-import com.google.protobuf.nano.NanoReferenceTypes;
-import com.google.protobuf.nano.NanoRepeatedPackables;
-import com.google.protobuf.nano.PackedExtensions;
-import com.google.protobuf.nano.RepeatedExtensions;
-import com.google.protobuf.nano.SingularExtensions;
-import com.google.protobuf.nano.TestRepeatedMergeNano;
-import com.google.protobuf.nano.UnittestMultipleNano;
 import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano;
 import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano;
 import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano;
@@ -67,6 +47,8 @@
 
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * Test nano runtime.
@@ -2688,6 +2670,7 @@
     msg.repeatedNestedEnum[0] = TestAllTypesNano.BAR;
     msg.repeatedNestedEnum[1] = TestAllTypesNano.FOO;
     msg.repeatedStringPiece = new String[] {null, "world"};
+    msg.setOneofString("hello");
 
     String protoPrint = msg.toString();
     assertTrue(protoPrint.contains("optional_int32: 14"));
@@ -2711,6 +2694,7 @@
     assertTrue(protoPrint.contains("default_string: \"hello\""));
     assertFalse(protoPrint.contains("repeated_string_piece: \"\""));  // null should be dropped
     assertTrue(protoPrint.contains("repeated_string_piece: \"world\""));
+    assertTrue(protoPrint.contains("oneof_string: \"hello\""));
   }
 
   public void testMessageNanoPrinterAccessors() throws Exception {
@@ -2749,6 +2733,45 @@
     assertTrue(protoPrint.contains("id: 33"));
   }
 
+  public void testMessageNanoPrinterForMaps() throws Exception {
+    TestMap msg = new TestMap();
+    MessageValue msgValues[] = new MessageValue[] {
+      new MessageValue(), new MessageValue()
+    };
+    msgValues[0].value = 1;
+    msgValues[1].value = 2;
+    msg.int32ToBytesField = new HashMap<Integer, byte[]>();
+    msg.int32ToBytesField.put(1, new byte[] {'"', '\0'});
+    msg.int32ToBytesField.put(2, new byte[] {1, 8});
+    msg.stringToInt32Field = new HashMap<String, Integer>();
+    msg.stringToInt32Field.put("hello", 1);
+    msg.stringToInt32Field.put("world", 2);
+    msg.int32ToMessageField = new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    msg.int32ToMessageField.put(0, msgValues[0]);
+    msg.int32ToMessageField.put(1, msgValues[1]);
+    msg.int32ToEnumField = new HashMap<Integer, Integer>();
+    msg.int32ToEnumField.put(1, 2);
+    msg.int32ToEnumField.put(2, 3);
+    String protoPrint = msg.toString();
+
+    assertTrue(protoPrint.contains(
+        "int32_to_bytes_field <\n  key: 1\n  value: \"\\\"\\000\"\n>"));
+    assertTrue(protoPrint.contains(
+        "int32_to_bytes_field <\n  key: 2\n  value: \"\\001\\010\"\n>"));
+    assertTrue(protoPrint.contains(
+        "string_to_int32_field <\n  key: \"hello\"\n  value: 1\n>"));
+    assertTrue(protoPrint.contains(
+        "string_to_int32_field <\n  key: \"world\"\n  value: 2\n>"));
+    assertTrue(protoPrint.contains(
+        "int32_to_message_field <\n  key: 0\n  value <\n    value: 1\n"));
+    assertTrue(protoPrint.contains(
+        "int32_to_message_field <\n  key: 1\n  value <\n    value: 2\n"));
+    assertTrue(protoPrint.contains(
+        "int32_to_enum_field <\n  key: 1\n  value: 2\n>"));
+    assertTrue(protoPrint.contains(
+        "int32_to_enum_field <\n  key: 2\n  value: 3\n>"));
+  }
+
   public void testExtensions() throws Exception {
     Extensions.ExtendableMessage message = new Extensions.ExtendableMessage();
     message.field = 5;
@@ -3340,6 +3363,7 @@
       TestAllTypesNano.BAR,
       TestAllTypesNano.BAZ
     };
+    message.setOneofUint32(3);
     return message;
   }
 
@@ -3538,6 +3562,259 @@
         new NanoReferenceTypes.TestAllTypesNano(), MessageNano.toByteArray(m7))));
   }
 
+  private static TestAllTypesNano generateMessageForOneof(int caseNumber) {
+    TestAllTypesNano result = new TestAllTypesNano();
+    TestAllTypesNano.NestedMessage nested =
+        new TestAllTypesNano.NestedMessage();
+    nested.bb = 2;
+    switch (caseNumber) {
+      case TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER:
+        result.setOneofUint32(1);
+        break;
+      case TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER:
+        result.setOneofEnum(TestAllTypesNano.BAR);
+        break;
+      case TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER:
+        result.setOneofNestedMessage(nested);
+        break;
+      case TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER:
+        result.setOneofBytes(new byte[] {1, 2});
+        break;
+      case TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER:
+        result.setOneofString("hello");
+        break;
+      case TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER:
+        result.setOneofFixed64(-1L);
+        break;
+      default:
+        throw new RuntimeException("unexpected case number: " + caseNumber);
+    }
+    return result;
+  }
+
+  public void testOneofHashCodeEquals() throws Exception {
+    TestAllTypesNano m1 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+    assertEquals(m1, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER));
+    assertFalse(m1.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m2 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+    assertEquals(m2, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER));
+    assertFalse(m2.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m3 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+    assertEquals(m3, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER));
+    assertFalse(m3.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m4 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+    assertEquals(m4, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER));
+    assertFalse(m4.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m5 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER);
+    assertEquals(m5, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER));
+    assertFalse(m5.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m6 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+    assertEquals(m6, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER));
+    assertFalse(m6.equals(new TestAllTypesNano()));
+
+    Map<TestAllTypesNano, Integer> map =
+        new HashMap<TestAllTypesNano, Integer>();
+    map.put(m1, 1);
+    map.put(m2, 2);
+    map.put(m3, 3);
+    map.put(m4, 4);
+    map.put(m5, 5);
+    map.put(m6, 6);
+
+    assertEquals(6, map.size());
+  }
+
+  private void checkOneofCase(TestAllTypesNano nano, int field)
+      throws Exception {
+    assertEquals(field, nano.getOneofFieldCase());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER,
+        nano.hasOneofBytes());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER,
+        nano.hasOneofEnum());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER,
+        nano.hasOneofFixed64());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER,
+        nano.hasOneofNestedMessage());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER,
+        nano.hasOneofString());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER,
+        nano.hasOneofUint32());
+
+  }
+
+  public void testOneofDefault() throws Exception {
+    TestAllTypesNano m1 = new TestAllTypesNano();
+    checkOneofCase(m1, 0);
+    assertEquals(WireFormatNano.EMPTY_BYTES, m1.getOneofBytes());
+    assertEquals(TestAllTypesNano.FOO, m1.getOneofEnum());
+    assertEquals(0L, m1.getOneofFixed64());
+    assertEquals(null, m1.getOneofNestedMessage());
+    assertEquals("", m1.getOneofString());
+    assertEquals(0, m1.getOneofUint32());
+  }
+
+  public void testOneofExclusiveness() throws Exception {
+    TestAllTypesNano m = new TestAllTypesNano();
+    checkOneofCase(m, 0);
+
+    m.setOneofBytes(new byte[]{0, 1});
+    checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+    assertTrue(Arrays.equals(new byte[]{0,  1}, m.getOneofBytes()));
+
+    m.setOneofEnum(TestAllTypesNano.BAZ);
+    checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+    assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+    assertEquals(WireFormatNano.EMPTY_BYTES, m.getOneofBytes());
+
+    m.setOneofFixed64(-1L);
+    checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+    assertEquals(-1L, m.getOneofFixed64());
+    assertEquals(TestAllTypesNano.FOO, m.getOneofEnum());
+
+    m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+    checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+    assertEquals(
+        new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage());
+    assertEquals(0L, m.getOneofFixed64());
+
+    m.setOneofString("hello");
+    checkOneofCase(m, TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER);
+    assertEquals("hello", m.getOneofString());
+    assertNull(m.getOneofNestedMessage());
+
+    m.setOneofUint32(10);
+    checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+    assertEquals(10, m.getOneofUint32());
+    assertEquals("", m.getOneofString());
+
+    m.setOneofBytes(new byte[]{0, 1});
+    checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+    assertTrue(Arrays.equals(new byte[]{0,  1}, m.getOneofBytes()));
+    assertEquals(0, m.getOneofUint32());
+  }
+
+  public void testOneofClear() throws Exception {
+    TestAllTypesNano m = new TestAllTypesNano();
+    m.setOneofBytes(new byte[]{0, 1});
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofEnum(TestAllTypesNano.BAZ);
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofFixed64(-1L);
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofString("hello");
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofUint32(10);
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+  }
+
+  public void testOneofMarshaling() throws Exception {
+    TestAllTypesNano m = new TestAllTypesNano();
+    TestAllTypesNano parsed = new TestAllTypesNano();
+    {
+      m.setOneofBytes(new byte[]{0, 1});
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(parsed, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+      assertTrue(Arrays.equals(new byte[]{0, 1}, parsed.getOneofBytes()));
+    }
+    {
+      m.setOneofEnum(TestAllTypesNano.BAZ);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+      assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+    }
+    {
+      m.setOneofEnum(TestAllTypesNano.BAZ);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+      assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+    }
+    {
+      m.setOneofFixed64(-1L);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+      assertEquals(-1L, m.getOneofFixed64());
+    }
+    {
+      m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+      assertEquals(
+          new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage());
+    }
+    {
+      m.setOneofString("hello");
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      assertEquals("hello", m.getOneofString());
+      assertNull(m.getOneofNestedMessage());
+    }
+    {
+      m.setOneofUint32(10);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+      assertEquals(10, m.getOneofUint32());
+    }
+  }
+
+  public void testOneofSerializedConcat() throws Exception {
+    TestAllTypesNano m1 = new TestAllTypesNano();
+    m1.setOneofBytes(new byte[] {0, 1});
+    byte[] b1 = MessageNano.toByteArray(m1);
+    TestAllTypesNano m2 = new TestAllTypesNano();
+    m2.setOneofEnum(TestAllTypesNano.BAZ);
+    byte[] b2 = MessageNano.toByteArray(m2);
+    byte[] b3 = new byte[b1.length + b2.length];
+    System.arraycopy(b1, 0, b3, 0, b1.length);
+    System.arraycopy(b2, 0, b3, b1.length, b2.length);
+    TestAllTypesNano parsed = new TestAllTypesNano();
+    MessageNano.mergeFrom(parsed, b3);
+    // the last on the wire wins.
+    checkOneofCase(parsed, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+    assertEquals(TestAllTypesNano.BAZ, parsed.getOneofEnum());
+  }
+
   public void testNullRepeatedFields() throws Exception {
     // Check that serialization after explicitly setting a repeated field
     // to null doesn't NPE.
@@ -3754,6 +4031,320 @@
     assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools));
   }
 
+  public void testMapsSerializeAndParse() throws Exception {
+    TestMap origin = new TestMap();
+    setMapMessage(origin);
+    assertMapMessageSet(origin);
+
+    byte[] output = MessageNano.toByteArray(origin);
+    TestMap parsed = new TestMap();
+    MessageNano.mergeFrom(parsed, output);
+  }
+
+  public void testMapSerializeRejectNull() throws Exception {
+    TestMap primitiveMap = new TestMap();
+    primitiveMap.int32ToInt32Field = new HashMap<Integer, Integer>();
+    primitiveMap.int32ToInt32Field.put(null, 1);
+    try {
+      MessageNano.toByteArray(primitiveMap);
+      fail("should reject null keys");
+    } catch (IllegalStateException e) {
+      // pass.
+    }
+
+    TestMap messageMap = new TestMap();
+    messageMap.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    messageMap.int32ToMessageField.put(0, null);
+    try {
+      MessageNano.toByteArray(messageMap);
+      fail("should reject null values");
+    } catch (IllegalStateException e) {
+      // pass.
+    }
+  }
+
+  /**
+   * Tests that merging bytes containing conflicting keys with override the
+   * message value instead of merging the message value into the existing entry.
+   */
+  public void testMapMergeOverrideMessageValues() throws Exception {
+    TestMap.MessageValue origValue = new TestMap.MessageValue();
+    origValue.value = 1;
+    origValue.value2 = 2;
+    TestMap.MessageValue newValue = new TestMap.MessageValue();
+    newValue.value = 3;
+
+    TestMap origMessage = new TestMap();
+    origMessage.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    origMessage.int32ToMessageField.put(1, origValue);
+
+    TestMap newMessage = new TestMap();
+    newMessage.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    newMessage.int32ToMessageField.put(1, newValue);
+    MessageNano.mergeFrom(origMessage,
+        MessageNano.toByteArray(newMessage));
+    TestMap.MessageValue mergedValue = origMessage.int32ToMessageField.get(1);
+    assertEquals(3, mergedValue.value);
+    assertEquals(0, mergedValue.value2);
+  }
+
+  /**
+   * Tests that when merging with empty entries,
+   * we will use default for the key and value, instead of null.
+   */
+  public void testMapMergeEmptyEntry() throws Exception {
+    TestMap testMap = new TestMap();
+    byte[] buffer = new byte[1024];
+    CodedOutputByteBufferNano output =
+        CodedOutputByteBufferNano.newInstance(buffer);
+    // An empty entry for int32_to_int32 map.
+    output.writeTag(1, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(0);
+    // An empty entry for int32_to_message map.
+    output.writeTag(5, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(0);
+
+    CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(
+        buffer, 0, buffer.length - output.spaceLeft());
+    testMap.mergeFrom(input);
+    assertNotNull(testMap.int32ToInt32Field);;
+    assertEquals(1, testMap.int32ToInt32Field.size());
+    assertEquals(Integer.valueOf(0), testMap.int32ToInt32Field.get(0));
+    assertNotNull(testMap.int32ToMessageField);
+    assertEquals(1, testMap.int32ToMessageField.size());
+    TestMap.MessageValue messageValue = testMap.int32ToMessageField.get(0);
+    assertNotNull(messageValue);
+    assertEquals(0, messageValue.value);
+    assertEquals(0, messageValue.value2);
+  }
+
+  public void testMapEquals() throws Exception {
+    TestMap a = new TestMap();
+    TestMap b = new TestMap();
+
+    // empty and null map fields are equal.
+    assertTestMapEqual(a, b);
+    a.int32ToBytesField = new HashMap<Integer, byte[]>();
+    assertTestMapEqual(a, b);
+
+    a.int32ToInt32Field = new HashMap<Integer, Integer>();
+    b.int32ToInt32Field = new HashMap<Integer, Integer>();
+    setMap(a.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values));
+    setMap(b.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values));
+    assertTestMapEqual(a, b);
+
+    a.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    b.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    setMap(a.int32ToMessageField,
+        deepCopy(int32Values), deepCopy(messageValues));
+    setMap(b.int32ToMessageField,
+        deepCopy(int32Values), deepCopy(messageValues));
+    assertTestMapEqual(a, b);
+
+    a.stringToInt32Field = new HashMap<String, Integer>();
+    b.stringToInt32Field = new HashMap<String, Integer>();
+    setMap(a.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values));
+    setMap(b.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values));
+    assertTestMapEqual(a, b);
+
+    a.int32ToBytesField = new HashMap<Integer, byte[]>();
+    b.int32ToBytesField = new HashMap<Integer, byte[]>();
+    setMap(a.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues));
+    setMap(b.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues));
+    assertTestMapEqual(a, b);
+
+    // Make sure the map implementation does not matter.
+    a.int32ToStringField = new TreeMap<Integer, String>();
+    b.int32ToStringField = new HashMap<Integer, String>();
+    setMap(a.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues));
+    setMap(b.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues));
+    assertTestMapEqual(a, b);
+
+    a.clear();
+    b.clear();
+
+    // unequal cases: different value
+    a.int32ToInt32Field = new HashMap<Integer, Integer>();
+    b.int32ToInt32Field = new HashMap<Integer, Integer>();
+    a.int32ToInt32Field.put(1, 1);
+    b.int32ToInt32Field.put(1, 2);
+    assertTestMapUnequal(a, b);
+    // unequal case: additional entry
+    b.int32ToInt32Field.put(1, 1);
+    b.int32ToInt32Field.put(2, 1);
+    assertTestMapUnequal(a, b);
+    a.int32ToInt32Field.put(2, 1);
+    assertTestMapEqual(a, b);
+
+    // unequal case: different message value.
+    a.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    b.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    MessageValue va = new MessageValue();
+    va.value = 1;
+    MessageValue vb = new MessageValue();
+    vb.value = 1;
+    a.int32ToMessageField.put(1, va);
+    b.int32ToMessageField.put(1, vb);
+    assertTestMapEqual(a, b);
+    vb.value = 2;
+    assertTestMapUnequal(a, b);
+  }
+
+  private static void assertTestMapEqual(TestMap a, TestMap b)
+      throws Exception {
+    assertEquals(a.hashCode(), b.hashCode());
+    assertTrue(a.equals(b));
+    assertTrue(b.equals(a));
+  }
+
+  private static void assertTestMapUnequal(TestMap a, TestMap b)
+      throws Exception {
+    assertFalse(a.equals(b));
+    assertFalse(b.equals(a));
+  }
+
+  private static final Integer[] int32Values = new Integer[] {
+    0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE,
+  };
+
+  private static final Long[] int64Values = new Long[] {
+    0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE,
+  };
+
+  private static final String[] stringValues = new String[] {
+    "", "hello", "world", "foo", "bar",
+  };
+
+  private static final byte[][] bytesValues = new byte[][] {
+    new byte[] {},
+    new byte[] {0},
+    new byte[] {1, -1},
+    new byte[] {127, -128},
+    new byte[] {'a', 'b', '0', '1'},
+  };
+
+  private static final Boolean[] boolValues = new Boolean[] {
+    false, true,
+  };
+
+  private static final Integer[] enumValues = new Integer[] {
+    TestMap.FOO, TestMap.BAR, TestMap.BAZ, TestMap.QUX,
+    Integer.MAX_VALUE /* unknown */,
+  };
+
+  private static final TestMap.MessageValue[] messageValues =
+      new TestMap.MessageValue[] {
+    newMapValueMessage(0),
+    newMapValueMessage(1),
+    newMapValueMessage(-1),
+    newMapValueMessage(Integer.MAX_VALUE),
+    newMapValueMessage(Integer.MIN_VALUE),
+  };
+
+  private static TestMap.MessageValue newMapValueMessage(int value) {
+    TestMap.MessageValue result = new TestMap.MessageValue();
+    result.value = value;
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static <T> T[] deepCopy(T[] orig) throws Exception {
+    if (orig instanceof MessageValue[]) {
+      MessageValue[] result = new MessageValue[orig.length];
+      for (int i = 0; i < orig.length; i++) {
+        result[i] = new MessageValue();
+        MessageNano.mergeFrom(
+            result[i], MessageNano.toByteArray((MessageValue) orig[i]));
+      }
+      return (T[]) result;
+    }
+    if (orig instanceof byte[][]) {
+      byte[][] result = new byte[orig.length][];
+      for (int i = 0; i < orig.length; i++) {
+        byte[] origBytes = (byte[]) orig[i];
+        result[i] = Arrays.copyOf(origBytes, origBytes.length);
+      }
+    }
+    return Arrays.copyOf(orig, orig.length);
+  }
+
+  private <K, V> void setMap(Map<K, V> map, K[] keys, V[] values) {
+    assert(keys.length == values.length);
+    for (int i = 0; i < keys.length; i++) {
+      map.put(keys[i], values[i]);
+    }
+  }
+
+  private <K, V> void assertMapSet(
+      Map<K, V> map, K[] keys, V[] values) throws Exception {
+    assert(keys.length == values.length);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals(values[i], map.get(keys[i]));
+    }
+    assertEquals(keys.length, map.size());
+  }
+
+  private void setMapMessage(TestMap testMap) {
+    testMap.int32ToInt32Field = new HashMap<Integer, Integer>();
+    testMap.int32ToBytesField = new HashMap<Integer, byte[]>();
+    testMap.int32ToEnumField = new HashMap<Integer, Integer>();
+    testMap.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    testMap.int32ToStringField = new HashMap<Integer, String>();
+    testMap.stringToInt32Field = new HashMap<String, Integer>();
+    testMap.boolToBoolField = new HashMap<Boolean, Boolean>();
+    testMap.uint32ToUint32Field = new HashMap<Integer, Integer>();
+    testMap.sint32ToSint32Field = new HashMap<Integer, Integer>();
+    testMap.fixed32ToFixed32Field = new HashMap<Integer, Integer>();
+    testMap.sfixed32ToSfixed32Field = new HashMap<Integer, Integer>();
+    testMap.int64ToInt64Field = new HashMap<Long, Long>();
+    testMap.uint64ToUint64Field = new HashMap<Long, Long>();
+    testMap.sint64ToSint64Field = new HashMap<Long, Long>();
+    testMap.fixed64ToFixed64Field = new HashMap<Long, Long>();
+    testMap.sfixed64ToSfixed64Field = new HashMap<Long, Long>();
+    setMap(testMap.int32ToInt32Field, int32Values, int32Values);
+    setMap(testMap.int32ToBytesField, int32Values, bytesValues);
+    setMap(testMap.int32ToEnumField, int32Values, enumValues);
+    setMap(testMap.int32ToMessageField, int32Values, messageValues);
+    setMap(testMap.int32ToStringField, int32Values, stringValues);
+    setMap(testMap.stringToInt32Field, stringValues, int32Values);
+    setMap(testMap.boolToBoolField, boolValues, boolValues);
+    setMap(testMap.uint32ToUint32Field, int32Values, int32Values);
+    setMap(testMap.sint32ToSint32Field, int32Values, int32Values);
+    setMap(testMap.fixed32ToFixed32Field, int32Values, int32Values);
+    setMap(testMap.sfixed32ToSfixed32Field, int32Values, int32Values);
+    setMap(testMap.int64ToInt64Field, int64Values, int64Values);
+    setMap(testMap.uint64ToUint64Field, int64Values, int64Values);
+    setMap(testMap.sint64ToSint64Field, int64Values, int64Values);
+    setMap(testMap.fixed64ToFixed64Field, int64Values, int64Values);
+    setMap(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
+  }
+  private void assertMapMessageSet(TestMap testMap) throws Exception {
+    assertMapSet(testMap.int32ToInt32Field, int32Values, int32Values);
+    assertMapSet(testMap.int32ToBytesField, int32Values, bytesValues);
+    assertMapSet(testMap.int32ToEnumField, int32Values, enumValues);
+    assertMapSet(testMap.int32ToMessageField, int32Values, messageValues);
+    assertMapSet(testMap.int32ToStringField, int32Values, stringValues);
+    assertMapSet(testMap.stringToInt32Field, stringValues, int32Values);
+    assertMapSet(testMap.boolToBoolField, boolValues, boolValues);
+    assertMapSet(testMap.uint32ToUint32Field, int32Values, int32Values);
+    assertMapSet(testMap.sint32ToSint32Field, int32Values, int32Values);
+    assertMapSet(testMap.fixed32ToFixed32Field, int32Values, int32Values);
+    assertMapSet(testMap.sfixed32ToSfixed32Field, int32Values, int32Values);
+    assertMapSet(testMap.int64ToInt64Field, int64Values, int64Values);
+    assertMapSet(testMap.uint64ToUint64Field, int64Values, int64Values);
+    assertMapSet(testMap.sint64ToSint64Field, int64Values, int64Values);
+    assertMapSet(testMap.fixed64ToFixed64Field, int64Values, int64Values);
+    assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
+  }
+
   private void assertRepeatedPackablesEqual(
       NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
     // Not using MessageNano.equals() -- that belongs to a separate test.
diff --git a/javanano/src/test/java/com/google/protobuf/nano/map_test.proto b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto
new file mode 100644
index 0000000..f72833a
--- /dev/null
+++ b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto
@@ -0,0 +1,70 @@
+// 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 map_test;
+
+option java_package = "com.google.protobuf.nano";
+option java_outer_classname = "MapTestProto";
+
+message TestMap {
+  message MessageValue {
+    int32 value = 1;
+    int32 value2 = 2;
+  }
+  enum EnumValue {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    QUX = 3;
+  }
+
+  map<int32, int32>        int32_to_int32_field = 1;
+  map<int32, string>       int32_to_string_field = 2;
+  map<int32, bytes>        int32_to_bytes_field = 3;
+  map<int32, EnumValue>    int32_to_enum_field = 4;
+  map<int32, MessageValue> int32_to_message_field = 5;
+  map<string, int32>       string_to_int32_field = 6;
+  map<bool, bool>          bool_to_bool_field = 7;
+
+  // Test all the other primitive types. As the key and value are not coupled in
+  // the implementation, we do not test all the combinations of key/value pairs,
+  // so that we can keep the number of test cases manageable
+  map<uint32, uint32>      uint32_to_uint32_field = 11;
+  map<sint32, sint32>      sint32_to_sint32_field = 12;
+  map<fixed32, fixed32>    fixed32_to_fixed32_field = 13;
+  map<sfixed32, sfixed32>  sfixed32_to_sfixed32_field = 14;
+  map<int64, int64>        int64_to_int64_field = 15;
+  map<uint64, uint64>      uint64_to_uint64_field = 16;
+  map<sint64, sint64>      sint64_to_sint64_field = 17;
+  map<fixed64, fixed64>    fixed64_to_fixed64_field = 18;
+  map<sfixed64, sfixed64>  sfixed64_to_sfixed64_field = 19;
+}
diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
index 4519533..efaf526 100644
--- a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
+++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
@@ -167,6 +167,15 @@
 
   // Try to fail with java reserved keywords
   optional int32 synchronized = 96;
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 123;
+    bytes oneof_bytes = 124;
+    fixed64 oneof_fixed64 = 115;
+    NestedEnum oneof_enum = 116;
+  }
 }
 
 message ForeignMessageNano {
diff --git a/post_process_dist.sh b/post_process_dist.sh
index 733fa08..3c01ed8 100755
--- a/post_process_dist.sh
+++ b/post_process_dist.sh
@@ -27,7 +27,7 @@
 
 set -ex
 
-LANGUAGES="cpp java python"
+LANGUAGES="cpp java javanano python ruby"
 BASENAME=`basename $1 .tar.gz`
 VERSION=${BASENAME:9}
 
diff --git a/python/README.txt b/python/README.txt
index 7d85245..04cb176 100644
--- a/python/README.txt
+++ b/python/README.txt
@@ -48,8 +48,9 @@
      $ python setup.py build
      $ python setup.py google_test
 
-     If you want to test c++ implementation, run:
-     $ python setup.py test --cpp_implementation
+     If you want to build/test c++ implementation, run:
+     $ python setup.py build --cpp_implementation
+     $ python setup.py google_test --cpp_implementation
 
    If some tests fail, this library may not work correctly on your
    system.  Continue at your own risk.
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index ec3b093..1345bd5 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -32,4 +32,4 @@
 #
 # Copyright 2007 Google Inc. All Rights Reserved.
 
-__version__ = '3.0.0-pre'
+__version__ = '3.0.0a3.dev0'
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index af571b7..f7a58ca 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -41,15 +41,13 @@
 from google.protobuf.internal import api_implementation
 
 
+_USE_C_DESCRIPTORS = False
 if api_implementation.Type() == 'cpp':
   # Used by MakeDescriptor in cpp mode
   import os
   import uuid
-
-  if api_implementation.Version() == 2:
-    from google.protobuf.pyext import _message
-  else:
-    from google.protobuf.internal import cpp_message
+  from google.protobuf.pyext import _message
+  _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False)
 
 
 class Error(Exception):
@@ -60,12 +58,29 @@
   """Error transforming between python proto type and corresponding C++ type."""
 
 
+if _USE_C_DESCRIPTORS:
+  # This metaclass allows to override the behavior of code like
+  #     isinstance(my_descriptor, FieldDescriptor)
+  # and make it return True when the descriptor is an instance of the extension
+  # type written in C++.
+  class DescriptorMetaclass(type):
+    def __instancecheck__(cls, obj):
+      if super(DescriptorMetaclass, cls).__instancecheck__(obj):
+        return True
+      if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
+        return True
+      return False
+else:
+  # The standard metaclass; nothing changes.
+  DescriptorMetaclass = type
+
+
 class DescriptorBase(object):
 
   """Descriptors base class.
 
   This class is the base of all descriptor classes. It provides common options
-  related functionaility.
+  related functionality.
 
   Attributes:
     has_options:  True if the descriptor has non-default options.  Usually it
@@ -75,6 +90,12 @@
         avoid some bootstrapping issues.
   """
 
+  __metaclass__ = DescriptorMetaclass
+  if _USE_C_DESCRIPTORS:
+    # The class, or tuple of classes, that are considered as "virtual
+    # subclasses" of this descriptor class.
+    _C_DESCRIPTOR_CLASS = ()
+
   def __init__(self, options, options_class_name):
     """Initialize the descriptor given its options message and the name of the
     class of the options message. The name of the class is required in case
@@ -235,13 +256,25 @@
     file: (FileDescriptor) Reference to file descriptor.
   """
 
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.Descriptor
+
+    def __new__(cls, name, full_name, filename, containing_type, fields,
+                nested_types, enum_types, extensions, options=None,
+                is_extendable=True, extension_ranges=None, oneofs=None,
+                file=None, serialized_start=None, serialized_end=None,
+                syntax=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      return _message.Message._GetMessageDescriptor(full_name)
+
   # NOTE(tmarek): The file argument redefining a builtin is nothing we can
   # fix right now since we don't know how many clients already rely on the
   # name of the argument.
   def __init__(self, name, full_name, filename, containing_type, fields,
                nested_types, enum_types, extensions, options=None,
                is_extendable=True, extension_ranges=None, oneofs=None,
-               file=None, serialized_start=None, serialized_end=None):  # pylint:disable=redefined-builtin
+               file=None, serialized_start=None, serialized_end=None,
+               syntax=None):  # pylint:disable=redefined-builtin
     """Arguments to __init__() are as described in the description
     of Descriptor fields above.
 
@@ -286,6 +319,7 @@
     self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
     for oneof in self.oneofs:
       oneof.containing_type = self
+    self.syntax = syntax or "proto2"
 
   def EnumValueName(self, enum, value):
     """Returns the string name of an enum value.
@@ -452,6 +486,19 @@
   FIRST_RESERVED_FIELD_NUMBER = 19000
   LAST_RESERVED_FIELD_NUMBER = 19999
 
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
+
+    def __new__(cls, name, full_name, index, number, type, cpp_type, label,
+                default_value, message_type, enum_type, containing_type,
+                is_extension, extension_scope, options=None,
+                has_default_value=True, containing_oneof=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      if is_extension:
+        return _message.Message._GetExtensionDescriptor(full_name)
+      else:
+        return _message.Message._GetFieldDescriptor(full_name)
+
   def __init__(self, name, full_name, index, number, type, cpp_type, label,
                default_value, message_type, enum_type, containing_type,
                is_extension, extension_scope, options=None,
@@ -481,20 +528,14 @@
     self.containing_oneof = containing_oneof
     if api_implementation.Type() == 'cpp':
       if is_extension:
-        if api_implementation.Version() == 2:
-          # pylint: disable=protected-access
-          self._cdescriptor = (
-              _message.Message._GetExtensionDescriptor(full_name))
-          # pylint: enable=protected-access
-        else:
-          self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
+        # pylint: disable=protected-access
+        self._cdescriptor = (
+            _message.Message._GetExtensionDescriptor(full_name))
+        # pylint: enable=protected-access
       else:
-        if api_implementation.Version() == 2:
-          # pylint: disable=protected-access
-          self._cdescriptor = _message.Message._GetFieldDescriptor(full_name)
-          # pylint: enable=protected-access
-        else:
-          self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
+        # pylint: disable=protected-access
+        self._cdescriptor = _message.Message._GetFieldDescriptor(full_name)
+        # pylint: enable=protected-access
     else:
       self._cdescriptor = None
 
@@ -544,6 +585,15 @@
       None to use default enum options.
   """
 
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
+
+    def __new__(cls, name, full_name, filename, values,
+                containing_type=None, options=None, file=None,
+                serialized_start=None, serialized_end=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      return _message.Message._GetEnumDescriptor(full_name)
+
   def __init__(self, name, full_name, filename, values,
                containing_type=None, options=None, file=None,
                serialized_start=None, serialized_end=None):
@@ -588,6 +638,17 @@
       None to use default enum value options options.
   """
 
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
+
+    def __new__(cls, name, index, number, type=None, options=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      # There is no way we can build a complete EnumValueDescriptor with the
+      # given parameters (the name of the Enum is not known, for example).
+      # Fortunately generated files just pass it to the EnumDescriptor()
+      # constructor, which will ignore it, so returning None is good enough.
+      return None
+
   def __init__(self, name, index, number, type=None, options=None):
     """Arguments are as described in the attribute description above."""
     super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions')
@@ -611,6 +672,13 @@
       oneof can contain.
   """
 
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
+
+    def __new__(cls, name, full_name, index, containing_type, fields):
+      _message.Message._CheckCalledFromGeneratedFile()
+      return _message.Message._GetOneofDescriptor(full_name)
+
   def __init__(self, name, full_name, index, containing_type, fields):
     """Arguments are as described in the attribute description above."""
     self.name = name
@@ -704,6 +772,7 @@
 
   name: name of file, relative to root of source tree.
   package: name of the package
+  syntax: string indicating syntax of the file (can be "proto2" or "proto3")
   serialized_pb: (str) Byte string of serialized
     descriptor_pb2.FileDescriptorProto.
   dependencies: List of other FileDescriptors this FileDescriptor depends on.
@@ -712,14 +781,31 @@
   extensions_by_name: Dict of extension names and their descriptors.
   """
 
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.FileDescriptor
+
+    def __new__(cls, name, package, options=None, serialized_pb=None,
+                dependencies=None, syntax=None):
+      # FileDescriptor() is called from various places, not only from generated
+      # files, to register dynamic proto files and messages.
+      # TODO(amauryfa): Expose BuildFile() as a public function and make this
+      # constructor an implementation detail.
+      if serialized_pb:
+        # pylint: disable=protected-access2
+        return _message.Message._BuildFile(serialized_pb)
+        # pylint: enable=protected-access
+      else:
+        return super(FileDescriptor, cls).__new__(cls)
+
   def __init__(self, name, package, options=None, serialized_pb=None,
-               dependencies=None):
+               dependencies=None, syntax=None):
     """Constructor."""
     super(FileDescriptor, self).__init__(options, 'FileOptions')
 
     self.message_types_by_name = {}
     self.name = name
     self.package = package
+    self.syntax = syntax or "proto2"
     self.serialized_pb = serialized_pb
 
     self.enum_types_by_name = {}
@@ -728,12 +814,9 @@
 
     if (api_implementation.Type() == 'cpp' and
         self.serialized_pb is not None):
-      if api_implementation.Version() == 2:
-        # pylint: disable=protected-access
-        _message.Message._BuildFile(self.serialized_pb)
-        # pylint: enable=protected-access
-      else:
-        cpp_message.BuildFile(self.serialized_pb)
+      # pylint: disable=protected-access
+      _message.Message._BuildFile(self.serialized_pb)
+      # pylint: enable=protected-access
 
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.FileDescriptorProto.
@@ -754,7 +837,8 @@
   return message
 
 
-def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True):
+def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
+                   syntax=None):
   """Make a protobuf Descriptor given a DescriptorProto protobuf.
 
   Handles nested descriptors. Note that this is limited to the scope of defining
@@ -766,6 +850,8 @@
     package: Optional package name for the new message Descriptor (string).
     build_file_if_cpp: Update the C++ descriptor pool if api matches.
                        Set to False on recursion, so no duplicates are created.
+    syntax: The syntax/semantics that should be used.  Set to "proto3" to get
+            proto3 field presence semantics.
   Returns:
     A Descriptor for protobuf messages.
   """
@@ -791,12 +877,13 @@
     else:
       file_descriptor_proto.name = proto_name + '.proto'
 
-    if api_implementation.Version() == 2:
-      # pylint: disable=protected-access
-      _message.Message._BuildFile(file_descriptor_proto.SerializeToString())
-      # pylint: enable=protected-access
-    else:
-      cpp_message.BuildFile(file_descriptor_proto.SerializeToString())
+    # pylint: disable=protected-access
+    result = _message.Message._BuildFile(
+        file_descriptor_proto.SerializeToString())
+    # pylint: enable=protected-access
+
+    if _USE_C_DESCRIPTORS:
+      return result.message_types_by_name[desc_proto.name]
 
   full_message_name = [desc_proto.name]
   if package: full_message_name.insert(0, package)
@@ -819,7 +906,8 @@
     # used by fields in the message, so no loops are possible here.
     nested_desc = MakeDescriptor(nested_proto,
                                  package='.'.join(full_message_name),
-                                 build_file_if_cpp=False)
+                                 build_file_if_cpp=False,
+                                 syntax=syntax)
     nested_types[full_name] = nested_desc
 
   fields = []
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index bcac513..7e7701f 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -64,6 +64,9 @@
 from google.protobuf import text_encoding
 
 
+_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS
+
+
 def _NormalizeFullyQualifiedName(name):
   """Remove leading period from fully-qualified type name.
 
@@ -271,58 +274,81 @@
       file_descriptor = descriptor.FileDescriptor(
           name=file_proto.name,
           package=file_proto.package,
+          syntax=file_proto.syntax,
           options=file_proto.options,
           serialized_pb=file_proto.SerializeToString(),
           dependencies=direct_deps)
-      scope = {}
-
-      # This loop extracts all the message and enum types from all the
-      # dependencoes of the file_proto. This is necessary to create the
-      # scope of available message types when defining the passed in
-      # file proto.
-      for dependency in built_deps:
-        scope.update(self._ExtractSymbols(
-            dependency.message_types_by_name.values()))
-        scope.update((_PrefixWithDot(enum.full_name), enum)
-                     for enum in dependency.enum_types_by_name.values())
-
-      for message_type in file_proto.message_type:
-        message_desc = self._ConvertMessageDescriptor(
-            message_type, file_proto.package, file_descriptor, scope)
-        file_descriptor.message_types_by_name[message_desc.name] = message_desc
-
-      for enum_type in file_proto.enum_type:
-        file_descriptor.enum_types_by_name[enum_type.name] = (
-            self._ConvertEnumDescriptor(enum_type, file_proto.package,
-                                        file_descriptor, None, scope))
-
-      for index, extension_proto in enumerate(file_proto.extension):
-        extension_desc = self.MakeFieldDescriptor(
-            extension_proto, file_proto.package, index, is_extension=True)
-        extension_desc.containing_type = self._GetTypeFromScope(
-            file_descriptor.package, extension_proto.extendee, scope)
-        self.SetFieldType(extension_proto, extension_desc,
-                          file_descriptor.package, scope)
-        file_descriptor.extensions_by_name[extension_desc.name] = extension_desc
-
-      for desc_proto in file_proto.message_type:
-        self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
-
-      if file_proto.package:
-        desc_proto_prefix = _PrefixWithDot(file_proto.package)
+      if _USE_C_DESCRIPTORS:
+        # When using C++ descriptors, all objects defined in the file were added
+        # to the C++ database when the FileDescriptor was built above.
+        # Just add them to this descriptor pool.
+        def _AddMessageDescriptor(message_desc):
+          self._descriptors[message_desc.full_name] = message_desc
+          for nested in message_desc.nested_types:
+            _AddMessageDescriptor(nested)
+          for enum_type in message_desc.enum_types:
+            _AddEnumDescriptor(enum_type)
+        def _AddEnumDescriptor(enum_desc):
+          self._enum_descriptors[enum_desc.full_name] = enum_desc
+        for message_type in file_descriptor.message_types_by_name.values():
+          _AddMessageDescriptor(message_type)
+        for enum_type in file_descriptor.enum_types_by_name.values():
+          _AddEnumDescriptor(enum_type)
       else:
-        desc_proto_prefix = ''
+        scope = {}
 
-      for desc_proto in file_proto.message_type:
-        desc = self._GetTypeFromScope(desc_proto_prefix, desc_proto.name, scope)
-        file_descriptor.message_types_by_name[desc_proto.name] = desc
+        # This loop extracts all the message and enum types from all the
+        # dependencies of the file_proto. This is necessary to create the
+        # scope of available message types when defining the passed in
+        # file proto.
+        for dependency in built_deps:
+          scope.update(self._ExtractSymbols(
+              dependency.message_types_by_name.values()))
+          scope.update((_PrefixWithDot(enum.full_name), enum)
+                       for enum in dependency.enum_types_by_name.values())
+
+        for message_type in file_proto.message_type:
+          message_desc = self._ConvertMessageDescriptor(
+              message_type, file_proto.package, file_descriptor, scope,
+              file_proto.syntax)
+          file_descriptor.message_types_by_name[message_desc.name] = (
+              message_desc)
+
+        for enum_type in file_proto.enum_type:
+          file_descriptor.enum_types_by_name[enum_type.name] = (
+              self._ConvertEnumDescriptor(enum_type, file_proto.package,
+                                          file_descriptor, None, scope))
+
+        for index, extension_proto in enumerate(file_proto.extension):
+          extension_desc = self.MakeFieldDescriptor(
+              extension_proto, file_proto.package, index, is_extension=True)
+          extension_desc.containing_type = self._GetTypeFromScope(
+              file_descriptor.package, extension_proto.extendee, scope)
+          self.SetFieldType(extension_proto, extension_desc,
+                            file_descriptor.package, scope)
+          file_descriptor.extensions_by_name[extension_desc.name] = (
+              extension_desc)
+
+        for desc_proto in file_proto.message_type:
+          self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
+
+        if file_proto.package:
+          desc_proto_prefix = _PrefixWithDot(file_proto.package)
+        else:
+          desc_proto_prefix = ''
+
+        for desc_proto in file_proto.message_type:
+          desc = self._GetTypeFromScope(
+              desc_proto_prefix, desc_proto.name, scope)
+          file_descriptor.message_types_by_name[desc_proto.name] = desc
+
       self.Add(file_proto)
       self._file_descriptors[file_proto.name] = file_descriptor
 
     return self._file_descriptors[file_proto.name]
 
   def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None,
-                                scope=None):
+                                scope=None, syntax=None):
     """Adds the proto to the pool in the specified package.
 
     Args:
@@ -349,7 +375,8 @@
       scope = {}
 
     nested = [
-        self._ConvertMessageDescriptor(nested, desc_name, file_desc, scope)
+        self._ConvertMessageDescriptor(
+            nested, desc_name, file_desc, scope, syntax)
         for nested in desc_proto.nested_type]
     enums = [
         self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
@@ -383,7 +410,8 @@
         extension_ranges=extension_ranges,
         file=file_desc,
         serialized_start=None,
-        serialized_end=None)
+        serialized_end=None,
+        syntax=syntax)
     for nested in desc.nested_types:
       nested.containing_type = desc
     for enum in desc.enum_types:
diff --git a/python/google/protobuf/internal/_parameterized.py b/python/google/protobuf/internal/_parameterized.py
new file mode 100755
index 0000000..6ed2330
--- /dev/null
+++ b/python/google/protobuf/internal/_parameterized.py
@@ -0,0 +1,438 @@
+#! /usr/bin/python
+#
+# 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.
+
+"""Adds support for parameterized tests to Python's unittest TestCase class.
+
+A parameterized test is a method in a test case that is invoked with different
+argument tuples.
+
+A simple example:
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       (1, 2, 3),
+       (4, 5, 9),
+       (1, 1, 3))
+    def testAddition(self, op1, op2, result):
+      self.assertEquals(result, op1 + op2)
+
+
+Each invocation is a separate test case and properly isolated just
+like a normal test method, with its own setUp/tearDown cycle. In the
+example above, there are three separate testcases, one of which will
+fail due to an assertion error (1 + 1 != 3).
+
+Parameters for invididual test cases can be tuples (with positional parameters)
+or dictionaries (with named parameters):
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       {'op1': 1, 'op2': 2, 'result': 3},
+       {'op1': 4, 'op2': 5, 'result': 9},
+    )
+    def testAddition(self, op1, op2, result):
+      self.assertEquals(result, op1 + op2)
+
+If a parameterized test fails, the error message will show the
+original test name (which is modified internally) and the arguments
+for the specific invocation, which are part of the string returned by
+the shortDescription() method on test cases.
+
+The id method of the test, used internally by the unittest framework,
+is also modified to show the arguments. To make sure that test names
+stay the same across several invocations, object representations like
+
+  >>> class Foo(object):
+  ...  pass
+  >>> repr(Foo())
+  '<__main__.Foo object at 0x23d8610>'
+
+are turned into '<__main__.Foo>'. For even more descriptive names,
+especially in test logs, you can use the NamedParameters decorator. In
+this case, only tuples are supported, and the first parameters has to
+be a string (or an object that returns an apt name when converted via
+str()):
+
+  class NamedExample(parameterized.ParameterizedTestCase):
+    @parameterized.NamedParameters(
+       ('Normal', 'aa', 'aaa', True),
+       ('EmptyPrefix', '', 'abc', True),
+       ('BothEmpty', '', '', True))
+    def testStartsWith(self, prefix, string, result):
+      self.assertEquals(result, strings.startswith(prefix))
+
+Named tests also have the benefit that they can be run individually
+from the command line:
+
+  $ testmodule.py NamedExample.testStartsWithNormal
+  .
+  --------------------------------------------------------------------
+  Ran 1 test in 0.000s
+
+  OK
+
+Parameterized Classes
+=====================
+If invocation arguments are shared across test methods in a single
+ParameterizedTestCase class, instead of decorating all test methods
+individually, the class itself can be decorated:
+
+  @parameterized.Parameters(
+    (1, 2, 3)
+    (4, 5, 9))
+  class ArithmeticTest(parameterized.ParameterizedTestCase):
+    def testAdd(self, arg1, arg2, result):
+      self.assertEqual(arg1 + arg2, result)
+
+    def testSubtract(self, arg2, arg2, result):
+      self.assertEqual(result - arg1, arg2)
+
+Inputs from Iterables
+=====================
+If parameters should be shared across several test cases, or are dynamically
+created from other sources, a single non-tuple iterable can be passed into
+the decorator. This iterable will be used to obtain the test cases:
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+      c.op1, c.op2, c.result for c in testcases
+    )
+    def testAddition(self, op1, op2, result):
+      self.assertEquals(result, op1 + op2)
+
+
+Single-Argument Test Methods
+============================
+If a test method takes only one argument, the single argument does not need to
+be wrapped into a tuple:
+
+  class NegativeNumberExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       -1, -3, -4, -5
+    )
+    def testIsNegative(self, arg):
+      self.assertTrue(IsNegative(arg))
+"""
+
+__author__ = 'tmarek@google.com (Torsten Marek)'
+
+import collections
+import functools
+import re
+import types
+import unittest
+import uuid
+
+from google.apputils import basetest
+
+ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
+_SEPARATOR = uuid.uuid1().hex
+_FIRST_ARG = object()
+_ARGUMENT_REPR = object()
+
+
+def _CleanRepr(obj):
+  return ADDR_RE.sub(r'<\1>', repr(obj))
+
+
+# Helper function formerly from the unittest module, removed from it in
+# Python 2.7.
+def _StrClass(cls):
+  return '%s.%s' % (cls.__module__, cls.__name__)
+
+
+def _NonStringIterable(obj):
+  return (isinstance(obj, collections.Iterable) and not
+          isinstance(obj, basestring))
+
+
+def _FormatParameterList(testcase_params):
+  if isinstance(testcase_params, collections.Mapping):
+    return ', '.join('%s=%s' % (argname, _CleanRepr(value))
+                     for argname, value in testcase_params.iteritems())
+  elif _NonStringIterable(testcase_params):
+    return ', '.join(map(_CleanRepr, testcase_params))
+  else:
+    return _FormatParameterList((testcase_params,))
+
+
+class _ParameterizedTestIter(object):
+  """Callable and iterable class for producing new test cases."""
+
+  def __init__(self, test_method, testcases, naming_type):
+    """Returns concrete test functions for a test and a list of parameters.
+
+    The naming_type is used to determine the name of the concrete
+    functions as reported by the unittest framework. If naming_type is
+    _FIRST_ARG, the testcases must be tuples, and the first element must
+    have a string representation that is a valid Python identifier.
+
+    Args:
+      test_method: The decorated test method.
+      testcases: (list of tuple/dict) A list of parameter
+                 tuples/dicts for individual test invocations.
+      naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR.
+    """
+    self._test_method = test_method
+    self.testcases = testcases
+    self._naming_type = naming_type
+
+  def __call__(self, *args, **kwargs):
+    raise RuntimeError('You appear to be running a parameterized test case '
+                       'without having inherited from parameterized.'
+                       'ParameterizedTestCase. This is bad because none of '
+                       'your test cases are actually being run.')
+
+  def __iter__(self):
+    test_method = self._test_method
+    naming_type = self._naming_type
+
+    def MakeBoundParamTest(testcase_params):
+      @functools.wraps(test_method)
+      def BoundParamTest(self):
+        if isinstance(testcase_params, collections.Mapping):
+          test_method(self, **testcase_params)
+        elif _NonStringIterable(testcase_params):
+          test_method(self, *testcase_params)
+        else:
+          test_method(self, testcase_params)
+
+      if naming_type is _FIRST_ARG:
+        # Signal the metaclass that the name of the test function is unique
+        # and descriptive.
+        BoundParamTest.__x_use_name__ = True
+        BoundParamTest.__name__ += str(testcase_params[0])
+        testcase_params = testcase_params[1:]
+      elif naming_type is _ARGUMENT_REPR:
+        # __x_extra_id__ is used to pass naming information to the __new__
+        # method of TestGeneratorMetaclass.
+        # The metaclass will make sure to create a unique, but nondescriptive
+        # name for this test.
+        BoundParamTest.__x_extra_id__ = '(%s)' % (
+            _FormatParameterList(testcase_params),)
+      else:
+        raise RuntimeError('%s is not a valid naming type.' % (naming_type,))
+
+      BoundParamTest.__doc__ = '%s(%s)' % (
+          BoundParamTest.__name__, _FormatParameterList(testcase_params))
+      if test_method.__doc__:
+        BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,)
+      return BoundParamTest
+    return (MakeBoundParamTest(c) for c in self.testcases)
+
+
+def _IsSingletonList(testcases):
+  """True iff testcases contains only a single non-tuple element."""
+  return len(testcases) == 1 and not isinstance(testcases[0], tuple)
+
+
+def _ModifyClass(class_object, testcases, naming_type):
+  assert not getattr(class_object, '_id_suffix', None), (
+      'Cannot add parameters to %s,'
+      ' which already has parameterized methods.' % (class_object,))
+  class_object._id_suffix = id_suffix = {}
+  for name, obj in class_object.__dict__.items():
+    if (name.startswith(unittest.TestLoader.testMethodPrefix)
+        and isinstance(obj, types.FunctionType)):
+      delattr(class_object, name)
+      methods = {}
+      _UpdateClassDictForParamTestCase(
+          methods, id_suffix, name,
+          _ParameterizedTestIter(obj, testcases, naming_type))
+      for name, meth in methods.iteritems():
+        setattr(class_object, name, meth)
+
+
+def _ParameterDecorator(naming_type, testcases):
+  """Implementation of the parameterization decorators.
+
+  Args:
+    naming_type: The naming type.
+    testcases: Testcase parameters.
+
+  Returns:
+    A function for modifying the decorated object.
+  """
+  def _Apply(obj):
+    if isinstance(obj, type):
+      _ModifyClass(
+          obj,
+          list(testcases) if not isinstance(testcases, collections.Sequence)
+          else testcases,
+          naming_type)
+      return obj
+    else:
+      return _ParameterizedTestIter(obj, testcases, naming_type)
+
+  if _IsSingletonList(testcases):
+    assert _NonStringIterable(testcases[0]), (
+        'Single parameter argument must be a non-string iterable')
+    testcases = testcases[0]
+
+  return _Apply
+
+
+def Parameters(*testcases):
+  """A decorator for creating parameterized tests.
+
+  See the module docstring for a usage example.
+  Args:
+    *testcases: Parameters for the decorated method, either a single
+                iterable, or a list of tuples/dicts/objects (for tests
+                with only one argument).
+
+  Returns:
+     A test generator to be handled by TestGeneratorMetaclass.
+  """
+  return _ParameterDecorator(_ARGUMENT_REPR, testcases)
+
+
+def NamedParameters(*testcases):
+  """A decorator for creating parameterized tests.
+
+  See the module docstring for a usage example. The first element of
+  each parameter tuple should be a string and will be appended to the
+  name of the test method.
+
+  Args:
+    *testcases: Parameters for the decorated method, either a single
+                iterable, or a list of tuples.
+
+  Returns:
+     A test generator to be handled by TestGeneratorMetaclass.
+  """
+  return _ParameterDecorator(_FIRST_ARG, testcases)
+
+
+class TestGeneratorMetaclass(type):
+  """Metaclass for test cases with test generators.
+
+  A test generator is an iterable in a testcase that produces callables. These
+  callables must be single-argument methods. These methods are injected into
+  the class namespace and the original iterable is removed. If the name of the
+  iterable conforms to the test pattern, the injected methods will be picked
+  up as tests by the unittest framework.
+
+  In general, it is supposed to be used in conjuction with the
+  Parameters decorator.
+  """
+
+  def __new__(mcs, class_name, bases, dct):
+    dct['_id_suffix'] = id_suffix = {}
+    for name, obj in dct.items():
+      if (name.startswith(unittest.TestLoader.testMethodPrefix) and
+          _NonStringIterable(obj)):
+        iterator = iter(obj)
+        dct.pop(name)
+        _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator)
+
+    return type.__new__(mcs, class_name, bases, dct)
+
+
+def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator):
+  """Adds individual test cases to a dictionary.
+
+  Args:
+    dct: The target dictionary.
+    id_suffix: The dictionary for mapping names to test IDs.
+    name: The original name of the test case.
+    iterator: The iterator generating the individual test cases.
+  """
+  for idx, func in enumerate(iterator):
+    assert callable(func), 'Test generators must yield callables, got %r' % (
+        func,)
+    if getattr(func, '__x_use_name__', False):
+      new_name = func.__name__
+    else:
+      new_name = '%s%s%d' % (name, _SEPARATOR, idx)
+    assert new_name not in dct, (
+        'Name of parameterized test case "%s" not unique' % (new_name,))
+    dct[new_name] = func
+    id_suffix[new_name] = getattr(func, '__x_extra_id__', '')
+
+
+class ParameterizedTestCase(basetest.TestCase):
+  """Base class for test cases using the Parameters decorator."""
+  __metaclass__ = TestGeneratorMetaclass
+
+  def _OriginalName(self):
+    return self._testMethodName.split(_SEPARATOR)[0]
+
+  def __str__(self):
+    return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__))
+
+  def id(self):  # pylint: disable=invalid-name
+    """Returns the descriptive ID of the test.
+
+    This is used internally by the unittesting framework to get a name
+    for the test to be used in reports.
+
+    Returns:
+      The test id.
+    """
+    return '%s.%s%s' % (_StrClass(self.__class__),
+                        self._OriginalName(),
+                        self._id_suffix.get(self._testMethodName, ''))
+
+
+def CoopParameterizedTestCase(other_base_class):
+  """Returns a new base class with a cooperative metaclass base.
+
+  This enables the ParameterizedTestCase to be used in combination
+  with other base classes that have custom metaclasses, such as
+  mox.MoxTestBase.
+
+  Only works with metaclasses that do not override type.__new__.
+
+  Example:
+
+    import google3
+    import mox
+
+    from google3.testing.pybase import parameterized
+
+    class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)):
+      ...
+
+  Args:
+    other_base_class: (class) A test case base class.
+
+  Returns:
+    A new class object.
+  """
+  metaclass = type(
+      'CoopMetaclass',
+      (other_base_class.__metaclass__,
+       TestGeneratorMetaclass), {})
+  return metaclass(
+      'CoopParameterizedTestCase',
+      (other_base_class, ParameterizedTestCase), {})
diff --git a/python/google/protobuf/internal/api_implementation.cc b/python/google/protobuf/internal/api_implementation.cc
index 83db40b..6db12e8 100644
--- a/python/google/protobuf/internal/api_implementation.cc
+++ b/python/google/protobuf/internal/api_implementation.cc
@@ -50,10 +50,7 @@
 // and
 //   PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
 #ifdef PYTHON_PROTO2_CPP_IMPL_V1
-#if PY_MAJOR_VERSION >= 3
-#error "PYTHON_PROTO2_CPP_IMPL_V1 is not supported under Python 3."
-#endif
-static int kImplVersion = 1;
+#error "PYTHON_PROTO2_CPP_IMPL_V1 is no longer supported."
 #else
 #ifdef PYTHON_PROTO2_CPP_IMPL_V2
 static int kImplVersion = 2;
@@ -62,14 +59,7 @@
 static int kImplVersion = 0;
 #else
 
-// The defaults are set here.  Python 3 uses the fast C++ APIv2 by default.
-// Python 2 still uses the Python version by default until some compatibility
-// issues can be worked around.
-#if PY_MAJOR_VERSION >= 3
-static int kImplVersion = 2;
-#else
-static int kImplVersion = 0;
-#endif
+static int kImplVersion = -1;  // -1 means "Unspecified by compiler flags".
 
 #endif  // PYTHON_PROTO2_PYTHON_IMPL
 #endif  // PYTHON_PROTO2_CPP_IMPL_V2
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
index f7926c1..8ba4357 100755
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -40,14 +40,33 @@
   # The compile-time constants in the _api_implementation module can be used to
   # switch to a certain implementation of the Python API at build time.
   _api_version = _api_implementation.api_version
-  del _api_implementation
+  _proto_extension_modules_exist_in_build = True
 except ImportError:
-  _api_version = 0
+  _api_version = -1  # Unspecified by compiler flags.
+  _proto_extension_modules_exist_in_build = False
+
+if _api_version == 1:
+  raise ValueError('api_version=1 is no longer supported.')
+if _api_version < 0:  # Still unspecified?
+  try:
+    # The presence of this module in a build allows the proto implementation to
+    # be upgraded merely via build deps rather than a compiler flag or the
+    # runtime environment variable.
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf import _use_fast_cpp_protos
+    # Work around a known issue in the classic bootstrap .par import hook.
+    if not _use_fast_cpp_protos:
+      raise ImportError('_use_fast_cpp_protos import succeeded but was None')
+    del _use_fast_cpp_protos
+    _api_version = 2
+  except ImportError:
+    if _proto_extension_modules_exist_in_build:
+      if sys.version_info[0] >= 3:  # Python 3 defaults to C++ impl v2.
+        _api_version = 2
+      # TODO(b/17427486): Make Python 2 default to C++ impl v2.
 
 _default_implementation_type = (
-    'python' if _api_version == 0 else 'cpp')
-_default_version_str = (
-    '1' if _api_version <= 1 else '2')
+    'python' if _api_version <= 0 else 'cpp')
 
 # This environment variable can be used to switch to a certain implementation
 # of the Python API, overriding the compile-time constants in the
@@ -64,13 +83,12 @@
 # _api_implementation module. Right now only 1 and 2 are valid values. Any other
 # value will be ignored.
 _implementation_version_str = os.getenv(
-    'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION',
-    _default_version_str)
+    'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2')
 
-if _implementation_version_str not in ('1', '2'):
+if _implementation_version_str != '2':
   raise ValueError(
-      "unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: '" +
-      _implementation_version_str + "' (supported versions: 1, 2)"
+      'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' +
+      _implementation_version_str + '" (supported versions: 2)'
       )
 
 _implementation_version = int(_implementation_version_str)
diff --git a/python/google/protobuf/internal/api_implementation_default_test.py b/python/google/protobuf/internal/api_implementation_default_test.py
deleted file mode 100644
index 78d5cf2..0000000
--- a/python/google/protobuf/internal/api_implementation_default_test.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#! /usr/bin/python
-#
-# 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.
-
-"""Test that the api_implementation defaults are what we expect."""
-
-import os
-import sys
-# Clear environment implementation settings before the google3 imports.
-os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', None)
-os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', None)
-
-# pylint: disable=g-import-not-at-top
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-
-
-class ApiImplementationDefaultTest(basetest.TestCase):
-
-  if sys.version_info.major <= 2:
-
-    def testThatPythonIsTheDefault(self):
-      """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail."""
-      self.assertEqual('python', api_implementation.Type())
-
-  else:
-
-    def testThatCppApiV2IsTheDefault(self):
-      """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail."""
-      self.assertEqual('cpp', api_implementation.Type())
-      self.assertEqual(2, api_implementation.Version())
-
-
-if __name__ == '__main__':
-  basetest.main()
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index 20bfa85..d976f9e 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -41,7 +41,6 @@
 
 __author__ = 'petar@google.com (Petar Petrov)'
 
-
 class BaseContainer(object):
 
   """Base container class."""
@@ -119,15 +118,23 @@
       self._message_listener.Modified()
 
   def extend(self, elem_seq):
-    """Extends by appending the given sequence. Similar to list.extend()."""
-    if not elem_seq:
-      return
+    """Extends by appending the given iterable. Similar to list.extend()."""
 
-    new_values = []
-    for elem in elem_seq:
-      new_values.append(self._type_checker.CheckValue(elem))
-    self._values.extend(new_values)
-    self._message_listener.Modified()
+    if elem_seq is None:
+      return
+    try:
+      elem_seq_iter = iter(elem_seq)
+    except TypeError:
+      if not elem_seq:
+        # silently ignore falsy inputs :-/.
+        # TODO(ptucker): Deprecate this behavior. b/18413862
+        return
+      raise
+
+    new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter]
+    if new_values:
+      self._values.extend(new_values)
+      self._message_listener.Modified()
 
   def MergeFrom(self, other):
     """Appends the contents of another repeated field of the same type to this
@@ -141,6 +148,12 @@
     self._values.remove(elem)
     self._message_listener.Modified()
 
+  def pop(self, key=-1):
+    """Removes and returns an item at a given index. Similar to list.pop()."""
+    value = self._values[key]
+    self.__delitem__(key)
+    return value
+
   def __setitem__(self, key, value):
     """Sets the item on the specified position."""
     if isinstance(key, slice):  # PY3
@@ -245,6 +258,12 @@
     self._values.remove(elem)
     self._message_listener.Modified()
 
+  def pop(self, key=-1):
+    """Removes and returns an item at a given index. Similar to list.pop()."""
+    value = self._values[key]
+    self.__delitem__(key)
+    return value
+
   def __getslice__(self, start, stop):
     """Retrieves the subset of items from between the specified indices."""
     return self._values[start:stop]
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index a4b9060..0f50060 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -621,9 +621,6 @@
       if value is None:
         value = field_dict.setdefault(key, new_default(message))
       while 1:
-        value = field_dict.get(key)
-        if value is None:
-          value = field_dict.setdefault(key, new_default(message))
         # Read length.
         (size, pos) = local_DecodeVarint(buffer, pos)
         new_pos = pos + size
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 3924f21..50c4dbb 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -34,12 +34,16 @@
 
 __author__ = 'robinson@google.com (Will Robinson)'
 
+import sys
+
 from google.apputils import basetest
 from google.protobuf import unittest_custom_options_pb2
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import descriptor_pb2
+from google.protobuf.internal import api_implementation
 from google.protobuf import descriptor
+from google.protobuf import symbol_database
 from google.protobuf import text_format
 
 
@@ -51,41 +55,28 @@
 class DescriptorTest(basetest.TestCase):
 
   def setUp(self):
-    self.my_file = descriptor.FileDescriptor(
+    file_proto = descriptor_pb2.FileDescriptorProto(
         name='some/filename/some.proto',
-        package='protobuf_unittest'
-        )
-    self.my_enum = descriptor.EnumDescriptor(
-        name='ForeignEnum',
-        full_name='protobuf_unittest.ForeignEnum',
-        filename=None,
-        file=self.my_file,
-        values=[
-          descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4),
-          descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5),
-          descriptor.EnumValueDescriptor(name='FOREIGN_BAZ', index=2, number=6),
-        ])
-    self.my_message = descriptor.Descriptor(
-        name='NestedMessage',
-        full_name='protobuf_unittest.TestAllTypes.NestedMessage',
-        filename=None,
-        file=self.my_file,
-        containing_type=None,
-        fields=[
-          descriptor.FieldDescriptor(
-            name='bb',
-            full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb',
-            index=0, number=1,
-            type=5, cpp_type=1, label=1,
-            has_default_value=False, default_value=0,
-            message_type=None, enum_type=None, containing_type=None,
-            is_extension=False, extension_scope=None),
-        ],
-        nested_types=[],
-        enum_types=[
-          self.my_enum,
-        ],
-        extensions=[])
+        package='protobuf_unittest')
+    message_proto = file_proto.message_type.add(
+        name='NestedMessage')
+    message_proto.field.add(
+        name='bb',
+        number=1,
+        type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32,
+        label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL)
+    enum_proto = message_proto.enum_type.add(
+        name='ForeignEnum')
+    enum_proto.value.add(name='FOREIGN_FOO', number=4)
+    enum_proto.value.add(name='FOREIGN_BAR', number=5)
+    enum_proto.value.add(name='FOREIGN_BAZ', number=6)
+
+    descriptor_pool = symbol_database.Default().pool
+    descriptor_pool.Add(file_proto)
+    self.my_file = descriptor_pool.FindFileByName(file_proto.name)
+    self.my_message = self.my_file.message_types_by_name[message_proto.name]
+    self.my_enum = self.my_message.enum_types_by_name[enum_proto.name]
+
     self.my_method = descriptor.MethodDescriptor(
         name='Bar',
         full_name='protobuf_unittest.TestService.Bar',
@@ -173,6 +164,11 @@
     self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2,
                      method_options.Extensions[method_opt1])
 
+    message_descriptor = (
+        unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR)
+    self.assertTrue(file_descriptor.has_options)
+    self.assertFalse(message_descriptor.has_options)
+
   def testDifferentCustomOptionTypes(self):
     kint32min = -2**31
     kint64min = -2**63
@@ -394,6 +390,108 @@
     self.assertEqual(self.my_file.name, 'some/filename/some.proto')
     self.assertEqual(self.my_file.package, 'protobuf_unittest')
 
+  @basetest.unittest.skipIf(
+      api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
+      'Immutability of descriptors is only enforced in v2 implementation')
+  def testImmutableCppDescriptor(self):
+    message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    with self.assertRaises(AttributeError):
+      message_descriptor.fields_by_name = None
+    with self.assertRaises(TypeError):
+      message_descriptor.fields_by_name['Another'] = None
+    with self.assertRaises(TypeError):
+      message_descriptor.fields.append(None)
+
+
+class GeneratedDescriptorTest(basetest.TestCase):
+  """Tests for the properties of descriptors in generated code."""
+
+  def CheckMessageDescriptor(self, message_descriptor):
+    # Basic properties
+    self.assertEqual(message_descriptor.name, 'TestAllTypes')
+    self.assertEqual(message_descriptor.full_name,
+                     'protobuf_unittest.TestAllTypes')
+    # Test equality and hashability
+    self.assertEqual(message_descriptor, message_descriptor)
+    self.assertEqual(message_descriptor.fields[0].containing_type,
+                     message_descriptor)
+    self.assertIn(message_descriptor, [message_descriptor])
+    self.assertIn(message_descriptor, {message_descriptor: None})
+    # Test field containers
+    self.CheckDescriptorSequence(message_descriptor.fields)
+    self.CheckDescriptorMapping(message_descriptor.fields_by_name)
+    self.CheckDescriptorMapping(message_descriptor.fields_by_number)
+
+  def CheckFieldDescriptor(self, field_descriptor):
+    # Basic properties
+    self.assertEqual(field_descriptor.name, 'optional_int32')
+    self.assertEqual(field_descriptor.full_name,
+                     'protobuf_unittest.TestAllTypes.optional_int32')
+    self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes')
+    # Test equality and hashability
+    self.assertEqual(field_descriptor, field_descriptor)
+    self.assertEqual(
+        field_descriptor.containing_type.fields_by_name['optional_int32'],
+        field_descriptor)
+    self.assertIn(field_descriptor, [field_descriptor])
+    self.assertIn(field_descriptor, {field_descriptor: None})
+
+  def CheckDescriptorSequence(self, sequence):
+    # Verifies that a property like 'messageDescriptor.fields' has all the
+    # properties of an immutable abc.Sequence.
+    self.assertGreater(len(sequence), 0)  # Sized
+    self.assertEqual(len(sequence), len(list(sequence)))  # Iterable
+    item = sequence[0]
+    self.assertEqual(item, sequence[0])
+    self.assertIn(item, sequence)  # Container
+    self.assertEqual(sequence.index(item), 0)
+    self.assertEqual(sequence.count(item), 1)
+    reversed_iterator = reversed(sequence)
+    self.assertEqual(list(reversed_iterator), list(sequence)[::-1])
+    self.assertRaises(StopIteration, next, reversed_iterator)
+
+  def CheckDescriptorMapping(self, mapping):
+    # Verifies that a property like 'messageDescriptor.fields' has all the
+    # properties of an immutable abc.Mapping.
+    self.assertGreater(len(mapping), 0)  # Sized
+    self.assertEqual(len(mapping), len(list(mapping)))  # Iterable
+    if sys.version_info.major >= 3:
+      key, item = next(iter(mapping.items()))
+    else:
+      key, item = mapping.items()[0]
+    self.assertIn(key, mapping)  # Container
+    self.assertEqual(mapping.get(key), item)
+    # keys(), iterkeys() &co
+    item = (next(iter(mapping.keys())), next(iter(mapping.values())))
+    self.assertEqual(item, next(iter(mapping.items())))
+    if sys.version_info.major < 3:
+      def CheckItems(seq, iterator):
+        self.assertEqual(next(iterator), seq[0])
+        self.assertEqual(list(iterator), seq[1:])
+      CheckItems(mapping.keys(), mapping.iterkeys())
+      CheckItems(mapping.values(), mapping.itervalues())
+      CheckItems(mapping.items(), mapping.iteritems())
+
+  def testDescriptor(self):
+    message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.CheckMessageDescriptor(message_descriptor)
+    field_descriptor = message_descriptor.fields_by_name['optional_int32']
+    self.CheckFieldDescriptor(field_descriptor)
+
+  def testCppDescriptorContainer(self):
+    # Check that the collection is still valid even if the parent disappeared.
+    enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum']
+    values = enum.values
+    del enum
+    self.assertEqual('FOO', values[0].name)
+
+  def testCppDescriptorContainer_Iterator(self):
+    # Same test with the iterator
+    enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum']
+    values_iter = iter(enum.values)
+    del enum
+    self.assertEqual('FOO', next(values_iter).name)
+
 
 class DescriptorCopyToProtoTest(basetest.TestCase):
   """Tests for CopyTo functions of Descriptor."""
@@ -588,10 +686,12 @@
         output_type: '.protobuf_unittest.BarResponse'
       >
       """
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestService.DESCRIPTOR,
-        descriptor_pb2.ServiceDescriptorProto,
-        TEST_SERVICE_ASCII)
+    # TODO(rocking): enable this test after the proto descriptor change is
+    # checked in.
+    #self._InternalTestCopyToProto(
+    #    unittest_pb2.TestService.DESCRIPTOR,
+    #    descriptor_pb2.ServiceDescriptorProto,
+    #    TEST_SERVICE_ASCII)
 
 
 class MakeDescriptorTest(basetest.TestCase):
diff --git a/python/google/protobuf/internal/import_test_package/BUILD b/python/google/protobuf/internal/import_test_package/BUILD
deleted file mode 100644
index 90e5950..0000000
--- a/python/google/protobuf/internal/import_test_package/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-# Description:
-#   An example package that contains nested protos that are imported from
-#   __init__.py. See testPackageInitializationImport in reflection_test.py for
-#   details.
-
-package(
-    default_visibility = ["//net/proto2/python/internal:__pkg__"],
-)
-
-proto_library(
-    name = "inner_proto",
-    srcs = ["inner.proto"],
-    py_api_version = 2,
-)
-
-proto_library(
-    name = "outer_proto",
-    srcs = ["outer.proto"],
-    py_api_version = 2,
-    deps = [":inner_proto"],
-)
-
-py_library(
-    name = "import_test_package",
-    srcs = ["__init__.py"],
-    deps = [":outer_proto"],
-)
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 42e2ad7..ed1298a 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -48,9 +48,12 @@
 import operator
 import pickle
 import sys
+import unittest
 
 from google.apputils import basetest
+from google.protobuf.internal import _parameterized
 from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
 from google.protobuf.internal import test_util
 from google.protobuf import message
@@ -69,88 +72,65 @@
   return isinf(val) and (val < 0)
 
 
+@_parameterized.Parameters(
+    (unittest_pb2),
+    (unittest_proto3_arena_pb2))
 class MessageTest(basetest.TestCase):
 
-  def testBadUtf8String(self):
+  def testBadUtf8String(self, message_module):
     if api_implementation.Type() != 'python':
       self.skipTest("Skipping testBadUtf8String, currently only the python "
                     "api implementation raises UnicodeDecodeError when a "
                     "string field contains bad utf-8.")
     bad_utf8_data = test_util.GoldenFileData('bad_utf8_string')
     with self.assertRaises(UnicodeDecodeError) as context:
-      unittest_pb2.TestAllTypes.FromString(bad_utf8_data)
-    self.assertIn('field: protobuf_unittest.TestAllTypes.optional_string',
-                  str(context.exception))
+      message_module.TestAllTypes.FromString(bad_utf8_data)
+    self.assertIn('TestAllTypes.optional_string', str(context.exception))
 
-  def testGoldenMessage(self):
-    golden_data = test_util.GoldenFileData(
-        'golden_message_oneof_implemented')
-    golden_message = unittest_pb2.TestAllTypes()
+  def testGoldenMessage(self, message_module):
+    # Proto3 doesn't have the "default_foo" members or foreign enums,
+    # and doesn't preserve unknown fields, so for proto3 we use a golden
+    # message that doesn't have these fields set.
+    if message_module is unittest_pb2:
+      golden_data = test_util.GoldenFileData(
+          'golden_message_oneof_implemented')
+    else:
+      golden_data = test_util.GoldenFileData('golden_message_proto3')
+
+    golden_message = message_module.TestAllTypes()
     golden_message.ParseFromString(golden_data)
-    test_util.ExpectAllFieldsSet(self, golden_message)
+    if message_module is unittest_pb2:
+      test_util.ExpectAllFieldsSet(self, golden_message)
     self.assertEqual(golden_data, golden_message.SerializeToString())
     golden_copy = copy.deepcopy(golden_message)
     self.assertEqual(golden_data, golden_copy.SerializeToString())
 
-  def testGoldenExtensions(self):
-    golden_data = test_util.GoldenFileData('golden_message')
-    golden_message = unittest_pb2.TestAllExtensions()
-    golden_message.ParseFromString(golden_data)
-    all_set = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(all_set)
-    self.assertEquals(all_set, golden_message)
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-    golden_copy = copy.deepcopy(golden_message)
-    self.assertEqual(golden_data, golden_copy.SerializeToString())
-
-  def testGoldenPackedMessage(self):
+  def testGoldenPackedMessage(self, message_module):
     golden_data = test_util.GoldenFileData('golden_packed_fields_message')
-    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message = message_module.TestPackedTypes()
     golden_message.ParseFromString(golden_data)
-    all_set = unittest_pb2.TestPackedTypes()
+    all_set = message_module.TestPackedTypes()
     test_util.SetAllPackedFields(all_set)
-    self.assertEquals(all_set, golden_message)
+    self.assertEqual(all_set, golden_message)
     self.assertEqual(golden_data, all_set.SerializeToString())
     golden_copy = copy.deepcopy(golden_message)
     self.assertEqual(golden_data, golden_copy.SerializeToString())
 
-  def testGoldenPackedExtensions(self):
-    golden_data = test_util.GoldenFileData('golden_packed_fields_message')
-    golden_message = unittest_pb2.TestPackedExtensions()
-    golden_message.ParseFromString(golden_data)
-    all_set = unittest_pb2.TestPackedExtensions()
-    test_util.SetAllPackedExtensions(all_set)
-    self.assertEquals(all_set, golden_message)
-    self.assertEqual(golden_data, all_set.SerializeToString())
-    golden_copy = copy.deepcopy(golden_message)
-    self.assertEqual(golden_data, golden_copy.SerializeToString())
-
-  def testPickleSupport(self):
+  def testPickleSupport(self, message_module):
     golden_data = test_util.GoldenFileData('golden_message')
-    golden_message = unittest_pb2.TestAllTypes()
+    golden_message = message_module.TestAllTypes()
     golden_message.ParseFromString(golden_data)
     pickled_message = pickle.dumps(golden_message)
 
     unpickled_message = pickle.loads(pickled_message)
-    self.assertEquals(unpickled_message, golden_message)
+    self.assertEqual(unpickled_message, golden_message)
 
-
-  def testPickleIncompleteProto(self):
-    golden_message = unittest_pb2.TestRequired(a=1)
-    pickled_message = pickle.dumps(golden_message)
-
-    unpickled_message = pickle.loads(pickled_message)
-    self.assertEquals(unpickled_message, golden_message)
-    self.assertEquals(unpickled_message.a, 1)
-    # This is still an incomplete proto - so serializing should fail
-    self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
-
-  def testPositiveInfinity(self):
+  def testPositiveInfinity(self, message_module):
     golden_data = (b'\x5D\x00\x00\x80\x7F'
                    b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
                    b'\xCD\x02\x00\x00\x80\x7F'
                    b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
-    golden_message = unittest_pb2.TestAllTypes()
+    golden_message = message_module.TestAllTypes()
     golden_message.ParseFromString(golden_data)
     self.assertTrue(IsPosInf(golden_message.optional_float))
     self.assertTrue(IsPosInf(golden_message.optional_double))
@@ -158,12 +138,12 @@
     self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
     self.assertEqual(golden_data, golden_message.SerializeToString())
 
-  def testNegativeInfinity(self):
+  def testNegativeInfinity(self, message_module):
     golden_data = (b'\x5D\x00\x00\x80\xFF'
                    b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
                    b'\xCD\x02\x00\x00\x80\xFF'
                    b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
-    golden_message = unittest_pb2.TestAllTypes()
+    golden_message = message_module.TestAllTypes()
     golden_message.ParseFromString(golden_data)
     self.assertTrue(IsNegInf(golden_message.optional_float))
     self.assertTrue(IsNegInf(golden_message.optional_double))
@@ -171,12 +151,12 @@
     self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
     self.assertEqual(golden_data, golden_message.SerializeToString())
 
-  def testNotANumber(self):
+  def testNotANumber(self, message_module):
     golden_data = (b'\x5D\x00\x00\xC0\x7F'
                    b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
                    b'\xCD\x02\x00\x00\xC0\x7F'
                    b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
-    golden_message = unittest_pb2.TestAllTypes()
+    golden_message = message_module.TestAllTypes()
     golden_message.ParseFromString(golden_data)
     self.assertTrue(isnan(golden_message.optional_float))
     self.assertTrue(isnan(golden_message.optional_double))
@@ -188,47 +168,47 @@
     # verify the serialized string can be converted into a correctly
     # behaving protocol buffer.
     serialized = golden_message.SerializeToString()
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
     message.ParseFromString(serialized)
     self.assertTrue(isnan(message.optional_float))
     self.assertTrue(isnan(message.optional_double))
     self.assertTrue(isnan(message.repeated_float[0]))
     self.assertTrue(isnan(message.repeated_double[0]))
 
-  def testPositiveInfinityPacked(self):
+  def testPositiveInfinityPacked(self, message_module):
     golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F'
                    b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
-    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message = message_module.TestPackedTypes()
     golden_message.ParseFromString(golden_data)
     self.assertTrue(IsPosInf(golden_message.packed_float[0]))
     self.assertTrue(IsPosInf(golden_message.packed_double[0]))
     self.assertEqual(golden_data, golden_message.SerializeToString())
 
-  def testNegativeInfinityPacked(self):
+  def testNegativeInfinityPacked(self, message_module):
     golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF'
                    b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
-    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message = message_module.TestPackedTypes()
     golden_message.ParseFromString(golden_data)
     self.assertTrue(IsNegInf(golden_message.packed_float[0]))
     self.assertTrue(IsNegInf(golden_message.packed_double[0]))
     self.assertEqual(golden_data, golden_message.SerializeToString())
 
-  def testNotANumberPacked(self):
+  def testNotANumberPacked(self, message_module):
     golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F'
                    b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
-    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message = message_module.TestPackedTypes()
     golden_message.ParseFromString(golden_data)
     self.assertTrue(isnan(golden_message.packed_float[0]))
     self.assertTrue(isnan(golden_message.packed_double[0]))
 
     serialized = golden_message.SerializeToString()
-    message = unittest_pb2.TestPackedTypes()
+    message = message_module.TestPackedTypes()
     message.ParseFromString(serialized)
     self.assertTrue(isnan(message.packed_float[0]))
     self.assertTrue(isnan(message.packed_double[0]))
 
-  def testExtremeFloatValues(self):
-    message = unittest_pb2.TestAllTypes()
+  def testExtremeFloatValues(self, message_module):
+    message = message_module.TestAllTypes()
 
     # Most positive exponent, no significand bits set.
     kMostPosExponentNoSigBits = math.pow(2, 127)
@@ -272,8 +252,8 @@
     message.ParseFromString(message.SerializeToString())
     self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
 
-  def testExtremeDoubleValues(self):
-    message = unittest_pb2.TestAllTypes()
+  def testExtremeDoubleValues(self, message_module):
+    message = message_module.TestAllTypes()
 
     # Most positive exponent, no significand bits set.
     kMostPosExponentNoSigBits = math.pow(2, 1023)
@@ -317,43 +297,43 @@
     message.ParseFromString(message.SerializeToString())
     self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
 
-  def testFloatPrinting(self):
-    message = unittest_pb2.TestAllTypes()
+  def testFloatPrinting(self, message_module):
+    message = message_module.TestAllTypes()
     message.optional_float = 2.0
     self.assertEqual(str(message), 'optional_float: 2.0\n')
 
-  def testHighPrecisionFloatPrinting(self):
-    message = unittest_pb2.TestAllTypes()
+  def testHighPrecisionFloatPrinting(self, message_module):
+    message = message_module.TestAllTypes()
     message.optional_double = 0.12345678912345678
     if sys.version_info.major >= 3:
       self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n')
     else:
       self.assertEqual(str(message), 'optional_double: 0.123456789123\n')
 
-  def testUnknownFieldPrinting(self):
-    populated = unittest_pb2.TestAllTypes()
+  def testUnknownFieldPrinting(self, message_module):
+    populated = message_module.TestAllTypes()
     test_util.SetAllNonLazyFields(populated)
-    empty = unittest_pb2.TestEmptyMessage()
+    empty = message_module.TestEmptyMessage()
     empty.ParseFromString(populated.SerializeToString())
     self.assertEqual(str(empty), '')
 
-  def testRepeatedNestedFieldIteration(self):
-    msg = unittest_pb2.TestAllTypes()
+  def testRepeatedNestedFieldIteration(self, message_module):
+    msg = message_module.TestAllTypes()
     msg.repeated_nested_message.add(bb=1)
     msg.repeated_nested_message.add(bb=2)
     msg.repeated_nested_message.add(bb=3)
     msg.repeated_nested_message.add(bb=4)
 
-    self.assertEquals([1, 2, 3, 4],
-                      [m.bb for m in msg.repeated_nested_message])
-    self.assertEquals([4, 3, 2, 1],
-                      [m.bb for m in reversed(msg.repeated_nested_message)])
-    self.assertEquals([4, 3, 2, 1],
-                      [m.bb for m in msg.repeated_nested_message[::-1]])
+    self.assertEqual([1, 2, 3, 4],
+                     [m.bb for m in msg.repeated_nested_message])
+    self.assertEqual([4, 3, 2, 1],
+                     [m.bb for m in reversed(msg.repeated_nested_message)])
+    self.assertEqual([4, 3, 2, 1],
+                     [m.bb for m in msg.repeated_nested_message[::-1]])
 
-  def testSortingRepeatedScalarFieldsDefaultComparator(self):
+  def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module):
     """Check some different types with the default comparator."""
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
 
     # TODO(mattp): would testing more scalar types strengthen test?
     message.repeated_int32.append(1)
@@ -388,9 +368,9 @@
     self.assertEqual(message.repeated_bytes[1], b'b')
     self.assertEqual(message.repeated_bytes[2], b'c')
 
-  def testSortingRepeatedScalarFieldsCustomComparator(self):
+  def testSortingRepeatedScalarFieldsCustomComparator(self, message_module):
     """Check some different types with custom comparator."""
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
 
     message.repeated_int32.append(-3)
     message.repeated_int32.append(-2)
@@ -408,9 +388,9 @@
     self.assertEqual(message.repeated_string[1], 'bb')
     self.assertEqual(message.repeated_string[2], 'aaa')
 
-  def testSortingRepeatedCompositeFieldsCustomComparator(self):
+  def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module):
     """Check passing a custom comparator to sort a repeated composite field."""
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
 
     message.repeated_nested_message.add().bb = 1
     message.repeated_nested_message.add().bb = 3
@@ -426,9 +406,9 @@
     self.assertEqual(message.repeated_nested_message[4].bb, 5)
     self.assertEqual(message.repeated_nested_message[5].bb, 6)
 
-  def testRepeatedCompositeFieldSortArguments(self):
+  def testRepeatedCompositeFieldSortArguments(self, message_module):
     """Check sorting a repeated composite field using list.sort() arguments."""
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
 
     get_bb = operator.attrgetter('bb')
     cmp_bb = lambda a, b: cmp(a.bb, b.bb)
@@ -452,9 +432,9 @@
     self.assertEqual([k.bb for k in message.repeated_nested_message],
                      [6, 5, 4, 3, 2, 1])
 
-  def testRepeatedScalarFieldSortArguments(self):
+  def testRepeatedScalarFieldSortArguments(self, message_module):
     """Check sorting a scalar field using list.sort() arguments."""
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
 
     message.repeated_int32.append(-3)
     message.repeated_int32.append(-2)
@@ -484,9 +464,9 @@
       message.repeated_string.sort(cmp=len_cmp, reverse=True)
       self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
 
-  def testRepeatedFieldsComparable(self):
-    m1 = unittest_pb2.TestAllTypes()
-    m2 = unittest_pb2.TestAllTypes()
+  def testRepeatedFieldsComparable(self, message_module):
+    m1 = message_module.TestAllTypes()
+    m2 = message_module.TestAllTypes()
     m1.repeated_int32.append(0)
     m1.repeated_int32.append(1)
     m1.repeated_int32.append(2)
@@ -519,6 +499,493 @@
 
     # TODO(anuraag): Implement extensiondict comparison in C++ and then add test
 
+  def ensureNestedMessageExists(self, msg, attribute):
+    """Make sure that a nested message object exists.
+
+    As soon as a nested message attribute is accessed, it will be present in the
+    _fields dict, without being marked as actually being set.
+    """
+    getattr(msg, attribute)
+    self.assertFalse(msg.HasField(attribute))
+
+  def testOneofGetCaseNonexistingField(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field')
+
+  def testOneofDefaultValues(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+
+    # Oneof is set even when setting it to a default value.
+    m.oneof_uint32 = 0
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_uint32'))
+    self.assertFalse(m.HasField('oneof_string'))
+
+    m.oneof_string = ""
+    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_string'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+
+  def testOneofSemantics(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+
+    m.oneof_uint32 = 11
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_uint32'))
+
+    m.oneof_string = u'foo'
+    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+    self.assertTrue(m.HasField('oneof_string'))
+
+    m.oneof_nested_message.bb = 11
+    self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_string'))
+    self.assertTrue(m.HasField('oneof_nested_message'))
+
+    m.oneof_bytes = b'bb'
+    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_nested_message'))
+    self.assertTrue(m.HasField('oneof_bytes'))
+
+  def testOneofCompositeFieldReadAccess(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+
+    self.ensureNestedMessageExists(m, 'oneof_nested_message')
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    self.assertEqual(11, m.oneof_uint32)
+
+  def testOneofWhichOneof(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+
+    m.oneof_uint32 = 11
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    if message_module is unittest_pb2:
+      self.assertTrue(m.HasField('oneof_field'))
+
+    m.oneof_bytes = b'bb'
+    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+
+    m.ClearField('oneof_bytes')
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+
+  def testOneofClearField(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m.ClearField('oneof_field')
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+
+  def testOneofClearSetField(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m.ClearField('oneof_uint32')
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+
+  def testOneofClearUnsetField(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    self.ensureNestedMessageExists(m, 'oneof_nested_message')
+    m.ClearField('oneof_nested_message')
+    self.assertEqual(11, m.oneof_uint32)
+    if message_module is unittest_pb2:
+      self.assertTrue(m.HasField('oneof_field'))
+    self.assertTrue(m.HasField('oneof_uint32'))
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+
+  def testOneofDeserialize(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m2 = message_module.TestAllTypes()
+    m2.ParseFromString(m.SerializeToString())
+    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+  def testOneofCopyFrom(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m2 = message_module.TestAllTypes()
+    m2.CopyFrom(m)
+    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+  def testOneofNestedMergeFrom(self, message_module):
+    m = message_module.NestedTestAllTypes()
+    m.payload.oneof_uint32 = 11
+    m2 = message_module.NestedTestAllTypes()
+    m2.payload.oneof_bytes = b'bb'
+    m2.child.payload.oneof_bytes = b'bb'
+    m2.MergeFrom(m)
+    self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
+    self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
+
+  def testOneofMessageMergeFrom(self, message_module):
+    m = message_module.NestedTestAllTypes()
+    m.payload.oneof_nested_message.bb = 11
+    m.child.payload.oneof_nested_message.bb = 12
+    m2 = message_module.NestedTestAllTypes()
+    m2.payload.oneof_uint32 = 13
+    m2.MergeFrom(m)
+    self.assertEqual('oneof_nested_message',
+                     m2.payload.WhichOneof('oneof_field'))
+    self.assertEqual('oneof_nested_message',
+                     m2.child.payload.WhichOneof('oneof_field'))
+
+  def testOneofNestedMessageInit(self, message_module):
+    m = message_module.TestAllTypes(
+        oneof_nested_message=message_module.TestAllTypes.NestedMessage())
+    self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
+
+  def testOneofClear(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m.Clear()
+    self.assertIsNone(m.WhichOneof('oneof_field'))
+    m.oneof_bytes = b'bb'
+    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+
+  def testAssignByteStringToUnicodeField(self, message_module):
+    """Assigning a byte string to a string field should result
+    in the value being converted to a Unicode string."""
+    m = message_module.TestAllTypes()
+    m.optional_string = str('')
+    self.assertTrue(isinstance(m.optional_string, unicode))
+
+# TODO(haberman): why are these tests Google-internal only?
+
+  def testLongValuedSlice(self, message_module):
+    """It should be possible to use long-valued indicies in slices
+
+    This didn't used to work in the v2 C++ implementation.
+    """
+    m = message_module.TestAllTypes()
+
+    # Repeated scalar
+    m.repeated_int32.append(1)
+    sl = m.repeated_int32[long(0):long(len(m.repeated_int32))]
+    self.assertEqual(len(m.repeated_int32), len(sl))
+
+    # Repeated composite
+    m.repeated_nested_message.add().bb = 3
+    sl = m.repeated_nested_message[long(0):long(len(m.repeated_nested_message))]
+    self.assertEqual(len(m.repeated_nested_message), len(sl))
+
+  def testExtendShouldNotSwallowExceptions(self, message_module):
+    """This didn't use to work in the v2 C++ implementation."""
+    m = message_module.TestAllTypes()
+    with self.assertRaises(NameError) as _:
+      m.repeated_int32.extend(a for i in range(10))  # pylint: disable=undefined-variable
+    with self.assertRaises(NameError) as _:
+      m.repeated_nested_enum.extend(
+          a for i in range(10))  # pylint: disable=undefined-variable
+
+  FALSY_VALUES = [None, False, 0, 0.0, b'', u'', bytearray(), [], {}, set()]
+
+  def testExtendInt32WithNothing(self, message_module):
+    """Test no-ops extending repeated int32 fields."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_int32)
+
+    # TODO(ptucker): Deprecate this behavior. b/18413862
+    for falsy_value in MessageTest.FALSY_VALUES:
+      m.repeated_int32.extend(falsy_value)
+      self.assertSequenceEqual([], m.repeated_int32)
+
+    m.repeated_int32.extend([])
+    self.assertSequenceEqual([], m.repeated_int32)
+
+  def testExtendFloatWithNothing(self, message_module):
+    """Test no-ops extending repeated float fields."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_float)
+
+    # TODO(ptucker): Deprecate this behavior. b/18413862
+    for falsy_value in MessageTest.FALSY_VALUES:
+      m.repeated_float.extend(falsy_value)
+      self.assertSequenceEqual([], m.repeated_float)
+
+    m.repeated_float.extend([])
+    self.assertSequenceEqual([], m.repeated_float)
+
+  def testExtendStringWithNothing(self, message_module):
+    """Test no-ops extending repeated string fields."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+
+    # TODO(ptucker): Deprecate this behavior. b/18413862
+    for falsy_value in MessageTest.FALSY_VALUES:
+      m.repeated_string.extend(falsy_value)
+      self.assertSequenceEqual([], m.repeated_string)
+
+    m.repeated_string.extend([])
+    self.assertSequenceEqual([], m.repeated_string)
+
+  def testExtendInt32WithPythonList(self, message_module):
+    """Test extending repeated int32 fields with python lists."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_int32)
+    m.repeated_int32.extend([0])
+    self.assertSequenceEqual([0], m.repeated_int32)
+    m.repeated_int32.extend([1, 2])
+    self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
+    m.repeated_int32.extend([3, 4])
+    self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
+
+  def testExtendFloatWithPythonList(self, message_module):
+    """Test extending repeated float fields with python lists."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_float)
+    m.repeated_float.extend([0.0])
+    self.assertSequenceEqual([0.0], m.repeated_float)
+    m.repeated_float.extend([1.0, 2.0])
+    self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
+    m.repeated_float.extend([3.0, 4.0])
+    self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
+
+  def testExtendStringWithPythonList(self, message_module):
+    """Test extending repeated string fields with python lists."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend([''])
+    self.assertSequenceEqual([''], m.repeated_string)
+    m.repeated_string.extend(['11', '22'])
+    self.assertSequenceEqual(['', '11', '22'], m.repeated_string)
+    m.repeated_string.extend(['33', '44'])
+    self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string)
+
+  def testExtendStringWithString(self, message_module):
+    """Test extending repeated string fields with characters from a string."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend('abc')
+    self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string)
+
+  class TestIterable(object):
+    """This iterable object mimics the behavior of numpy.array.
+
+    __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1.
+
+    """
+
+    def __init__(self, values=None):
+      self._list = values or []
+
+    def __nonzero__(self):
+      size = len(self._list)
+      if size == 0:
+        return False
+      if size == 1:
+        return bool(self._list[0])
+      raise ValueError('Truth value is ambiguous.')
+
+    def __len__(self):
+      return len(self._list)
+
+    def __iter__(self):
+      return self._list.__iter__()
+
+  def testExtendInt32WithIterable(self, message_module):
+    """Test extending repeated int32 fields with iterable."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([]))
+    self.assertSequenceEqual([], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([0]))
+    self.assertSequenceEqual([0], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([1, 2]))
+    self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([3, 4]))
+    self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
+
+  def testExtendFloatWithIterable(self, message_module):
+    """Test extending repeated float fields with iterable."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([]))
+    self.assertSequenceEqual([], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([0.0]))
+    self.assertSequenceEqual([0.0], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0]))
+    self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0]))
+    self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
+
+  def testExtendStringWithIterable(self, message_module):
+    """Test extending repeated string fields with iterable."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable([]))
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable(['']))
+    self.assertSequenceEqual([''], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable(['1', '2']))
+    self.assertSequenceEqual(['', '1', '2'], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable(['3', '4']))
+    self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string)
+
+  def testPickleRepeatedScalarContainer(self, message_module):
+    # TODO(tibell): The pure-Python implementation support pickling of
+    #   scalar containers in *some* cases. For now the cpp2 version
+    #   throws an exception to avoid a segfault. Investigate if we
+    #   want to support pickling of these fields.
+    #
+    # For more information see: https://b2.corp.google.com/u/0/issues/18677897
+    if (api_implementation.Type() != 'cpp' or
+        api_implementation.Version() == 2):
+      return
+    m = message_module.TestAllTypes()
+    with self.assertRaises(pickle.PickleError) as _:
+      pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL)
+
+
+  def testSortEmptyRepeatedCompositeContainer(self, message_module):
+    """Exercise a scenario that has led to segfaults in the past.
+    """
+    m = message_module.TestAllTypes()
+    m.repeated_nested_message.sort()
+
+  def testHasFieldOnRepeatedField(self, message_module):
+    """Using HasField on a repeated field should raise an exception.
+    """
+    m = message_module.TestAllTypes()
+    with self.assertRaises(ValueError) as _:
+      m.HasField('repeated_int32')
+
+  def testRepeatedScalarFieldPop(self, message_module):
+    m = message_module.TestAllTypes()
+    with self.assertRaises(IndexError) as _:
+      m.repeated_int32.pop()
+    m.repeated_int32.extend(range(5))
+    self.assertEqual(4, m.repeated_int32.pop())
+    self.assertEqual(0, m.repeated_int32.pop(0))
+    self.assertEqual(2, m.repeated_int32.pop(1))
+    self.assertEqual([1, 3], m.repeated_int32)
+
+  def testRepeatedCompositeFieldPop(self, message_module):
+    m = message_module.TestAllTypes()
+    with self.assertRaises(IndexError) as _:
+      m.repeated_nested_message.pop()
+    for i in range(5):
+      n = m.repeated_nested_message.add()
+      n.bb = i
+    self.assertEqual(4, m.repeated_nested_message.pop().bb)
+    self.assertEqual(0, m.repeated_nested_message.pop(0).bb)
+    self.assertEqual(2, m.repeated_nested_message.pop(1).bb)
+    self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message])
+
+
+# Class to test proto2-only features (required, extensions, etc.)
+class Proto2Test(basetest.TestCase):
+
+  def testFieldPresence(self):
+    message = unittest_pb2.TestAllTypes()
+
+    self.assertFalse(message.HasField("optional_int32"))
+    self.assertFalse(message.HasField("optional_bool"))
+    self.assertFalse(message.HasField("optional_nested_message"))
+
+    with self.assertRaises(ValueError):
+      message.HasField("field_doesnt_exist")
+
+    with self.assertRaises(ValueError):
+      message.HasField("repeated_int32")
+    with self.assertRaises(ValueError):
+      message.HasField("repeated_nested_message")
+
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
+
+    # Fields are set even when setting the values to default values.
+    message.optional_int32 = 0
+    message.optional_bool = False
+    message.optional_nested_message.bb = 0
+    self.assertTrue(message.HasField("optional_int32"))
+    self.assertTrue(message.HasField("optional_bool"))
+    self.assertTrue(message.HasField("optional_nested_message"))
+
+    # Set the fields to non-default values.
+    message.optional_int32 = 5
+    message.optional_bool = True
+    message.optional_nested_message.bb = 15
+
+    self.assertTrue(message.HasField("optional_int32"))
+    self.assertTrue(message.HasField("optional_bool"))
+    self.assertTrue(message.HasField("optional_nested_message"))
+
+    # Clearing the fields unsets them and resets their value to default.
+    message.ClearField("optional_int32")
+    message.ClearField("optional_bool")
+    message.ClearField("optional_nested_message")
+
+    self.assertFalse(message.HasField("optional_int32"))
+    self.assertFalse(message.HasField("optional_bool"))
+    self.assertFalse(message.HasField("optional_nested_message"))
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
+
+  # TODO(tibell): The C++ implementations actually allows assignment
+  # of unknown enum values to *scalar* fields (but not repeated
+  # fields). Once checked enum fields becomes the default in the
+  # Python implementation, the C++ implementation should follow suit.
+  def testAssignInvalidEnum(self):
+    """It should not be possible to assign an invalid enum number to an
+    enum field."""
+    m = unittest_pb2.TestAllTypes()
+
+    with self.assertRaises(ValueError) as _:
+      m.optional_nested_enum = 1234567
+    self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567)
+
+  def testGoldenExtensions(self):
+    golden_data = test_util.GoldenFileData('golden_message')
+    golden_message = unittest_pb2.TestAllExtensions()
+    golden_message.ParseFromString(golden_data)
+    all_set = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(all_set)
+    self.assertEqual(all_set, golden_message)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testGoldenPackedExtensions(self):
+    golden_data = test_util.GoldenFileData('golden_packed_fields_message')
+    golden_message = unittest_pb2.TestPackedExtensions()
+    golden_message.ParseFromString(golden_data)
+    all_set = unittest_pb2.TestPackedExtensions()
+    test_util.SetAllPackedExtensions(all_set)
+    self.assertEqual(all_set, golden_message)
+    self.assertEqual(golden_data, all_set.SerializeToString())
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testPickleIncompleteProto(self):
+    golden_message = unittest_pb2.TestRequired(a=1)
+    pickled_message = pickle.dumps(golden_message)
+
+    unpickled_message = pickle.loads(pickled_message)
+    self.assertEqual(unpickled_message, golden_message)
+    self.assertEqual(unpickled_message.a, 1)
+    # This is still an incomplete proto - so serializing should fail
+    self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
+
+
+  # TODO(haberman): this isn't really a proto2-specific test except that this
+  # message has a required field in it.  Should probably be factored out so
+  # that we can test the other parts with proto3.
   def testParsingMerge(self):
     """Check the merge behavior when a required or optional field appears
     multiple times in the input."""
@@ -568,131 +1035,84 @@
     self.assertEqual(len(parsing_merge.Extensions[
         unittest_pb2.TestParsingMerge.repeated_ext]), 3)
 
-  def ensureNestedMessageExists(self, msg, attribute):
-    """Make sure that a nested message object exists.
 
-    As soon as a nested message attribute is accessed, it will be present in the
-    _fields dict, without being marked as actually being set.
-    """
-    getattr(msg, attribute)
-    self.assertFalse(msg.HasField(attribute))
+# Class to test proto3-only features/behavior (updated field presence & enums)
+class Proto3Test(basetest.TestCase):
 
-  def testOneofGetCaseNonexistingField(self):
-    m = unittest_pb2.TestAllTypes()
-    self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field')
+  def testFieldPresence(self):
+    message = unittest_proto3_arena_pb2.TestAllTypes()
 
-  def testOneofSemantics(self):
-    m = unittest_pb2.TestAllTypes()
-    self.assertIs(None, m.WhichOneof('oneof_field'))
+    # We can't test presence of non-repeated, non-submessage fields.
+    with self.assertRaises(ValueError):
+      message.HasField("optional_int32")
+    with self.assertRaises(ValueError):
+      message.HasField("optional_float")
+    with self.assertRaises(ValueError):
+      message.HasField("optional_string")
+    with self.assertRaises(ValueError):
+      message.HasField("optional_bool")
 
-    m.oneof_uint32 = 11
-    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
-    self.assertTrue(m.HasField('oneof_uint32'))
+    # But we can still test presence of submessage fields.
+    self.assertFalse(message.HasField("optional_nested_message"))
 
-    m.oneof_string = u'foo'
-    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
-    self.assertFalse(m.HasField('oneof_uint32'))
-    self.assertTrue(m.HasField('oneof_string'))
+    # As with proto2, we can't test presence of fields that don't exist, or
+    # repeated fields.
+    with self.assertRaises(ValueError):
+      message.HasField("field_doesnt_exist")
 
-    m.oneof_nested_message.bb = 11
-    self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
-    self.assertFalse(m.HasField('oneof_string'))
-    self.assertTrue(m.HasField('oneof_nested_message'))
+    with self.assertRaises(ValueError):
+      message.HasField("repeated_int32")
+    with self.assertRaises(ValueError):
+      message.HasField("repeated_nested_message")
 
-    m.oneof_bytes = b'bb'
-    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
-    self.assertFalse(m.HasField('oneof_nested_message'))
-    self.assertTrue(m.HasField('oneof_bytes'))
+    # Fields should default to their type-specific default.
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(0, message.optional_float)
+    self.assertEqual("", message.optional_string)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
 
-  def testOneofCompositeFieldReadAccess(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
+    # Setting a submessage should still return proper presence information.
+    message.optional_nested_message.bb = 0
+    self.assertTrue(message.HasField("optional_nested_message"))
 
-    self.ensureNestedMessageExists(m, 'oneof_nested_message')
-    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
-    self.assertEqual(11, m.oneof_uint32)
+    # Set the fields to non-default values.
+    message.optional_int32 = 5
+    message.optional_float = 1.1
+    message.optional_string = "abc"
+    message.optional_bool = True
+    message.optional_nested_message.bb = 15
 
-  def testOneofHasField(self):
-    m = unittest_pb2.TestAllTypes()
-    self.assertFalse(m.HasField('oneof_field'))
-    m.oneof_uint32 = 11
-    self.assertTrue(m.HasField('oneof_field'))
-    m.oneof_bytes = b'bb'
-    self.assertTrue(m.HasField('oneof_field'))
-    m.ClearField('oneof_bytes')
-    self.assertFalse(m.HasField('oneof_field'))
+    # Clearing the fields unsets them and resets their value to default.
+    message.ClearField("optional_int32")
+    message.ClearField("optional_float")
+    message.ClearField("optional_string")
+    message.ClearField("optional_bool")
+    message.ClearField("optional_nested_message")
 
-  def testOneofClearField(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    m.ClearField('oneof_field')
-    self.assertFalse(m.HasField('oneof_field'))
-    self.assertFalse(m.HasField('oneof_uint32'))
-    self.assertIs(None, m.WhichOneof('oneof_field'))
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(0, message.optional_float)
+    self.assertEqual("", message.optional_string)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
 
-  def testOneofClearSetField(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    m.ClearField('oneof_uint32')
-    self.assertFalse(m.HasField('oneof_field'))
-    self.assertFalse(m.HasField('oneof_uint32'))
-    self.assertIs(None, m.WhichOneof('oneof_field'))
+  def testAssignUnknownEnum(self):
+    """Assigning an unknown enum value is allowed and preserves the value."""
+    m = unittest_proto3_arena_pb2.TestAllTypes()
 
-  def testOneofClearUnsetField(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    self.ensureNestedMessageExists(m, 'oneof_nested_message')
-    m.ClearField('oneof_nested_message')
-    self.assertEqual(11, m.oneof_uint32)
-    self.assertTrue(m.HasField('oneof_field'))
-    self.assertTrue(m.HasField('oneof_uint32'))
-    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    m.optional_nested_enum = 1234567
+    self.assertEqual(1234567, m.optional_nested_enum)
+    m.repeated_nested_enum.append(22334455)
+    self.assertEqual(22334455, m.repeated_nested_enum[0])
+    # Assignment is a different code path than append for the C++ impl.
+    m.repeated_nested_enum[0] = 7654321
+    self.assertEqual(7654321, m.repeated_nested_enum[0])
+    serialized = m.SerializeToString()
 
-  def testOneofDeserialize(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    m2 = unittest_pb2.TestAllTypes()
-    m2.ParseFromString(m.SerializeToString())
-    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
-
-  def testOneofCopyFrom(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    m2 = unittest_pb2.TestAllTypes()
-    m2.CopyFrom(m)
-    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
-
-  def testOneofNestedMergeFrom(self):
-    m = unittest_pb2.NestedTestAllTypes()
-    m.payload.oneof_uint32 = 11
-    m2 = unittest_pb2.NestedTestAllTypes()
-    m2.payload.oneof_bytes = b'bb'
-    m2.child.payload.oneof_bytes = b'bb'
-    m2.MergeFrom(m)
-    self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
-    self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
-
-  def testOneofClear(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    m.Clear()
-    self.assertIsNone(m.WhichOneof('oneof_field'))
-    m.oneof_bytes = b'bb'
-    self.assertTrue(m.HasField('oneof_field'))
-
-
-  def testSortEmptyRepeatedCompositeContainer(self):
-    """Exercise a scenario that has led to segfaults in the past.
-    """
-    m = unittest_pb2.TestAllTypes()
-    m.repeated_nested_message.sort()
-
-  def testHasFieldOnRepeatedField(self):
-    """Using HasField on a repeated field should raise an exception.
-    """
-    m = unittest_pb2.TestAllTypes()
-    with self.assertRaises(ValueError) as _:
-      m.HasField('repeated_int32')
+    m2 = unittest_proto3_arena_pb2.TestAllTypes()
+    m2.ParseFromString(serialized)
+    self.assertEqual(1234567, m2.optional_nested_enum)
+    self.assertEqual(7654321, m2.repeated_nested_enum[0])
 
 
 class ValidTypeNamesTest(basetest.TestCase):
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index 6fda6ae..6ad0f90 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -219,12 +219,20 @@
 
   def AddDecoder(wiretype, is_packed):
     tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
-    cls._decoders_by_tag[tag_bytes] = (
-        type_checkers.TYPE_TO_DECODER[field_descriptor.type](
-            field_descriptor.number, is_repeated, is_packed,
-            field_descriptor, field_descriptor._default_constructor),
-        field_descriptor if field_descriptor.containing_oneof is not None
-        else None)
+    decode_type = field_descriptor.type
+    if (decode_type == _FieldDescriptor.TYPE_ENUM and
+        type_checkers.SupportsOpenEnums(field_descriptor)):
+      decode_type = _FieldDescriptor.TYPE_INT32
+
+    oneof_descriptor = None
+    if field_descriptor.containing_oneof is not None:
+      oneof_descriptor = field_descriptor
+
+    field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
+        field_descriptor.number, is_repeated, is_packed,
+        field_descriptor, field_descriptor._default_constructor)
+
+    cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
 
   AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
              False)
@@ -296,6 +304,8 @@
     def MakeSubMessageDefault(message):
       result = message_type._concrete_class()
       result._SetListener(message._listener_for_children)
+      if field.containing_oneof:
+        message._UpdateOneofState(field)
       return result
     return MakeSubMessageDefault
 
@@ -476,6 +486,7 @@
   type_checker = type_checkers.GetTypeChecker(field)
   default_value = field.default_value
   valid_values = set()
+  is_proto3 = field.containing_type.syntax == "proto3"
 
   def getter(self):
     # TODO(protobuf-team): This may be broken since there may not be
@@ -483,15 +494,24 @@
     return self._fields.get(field, default_value)
   getter.__module__ = None
   getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+  clear_when_set_to_default = is_proto3 and not field.containing_oneof
+
   def field_setter(self, new_value):
     # pylint: disable=protected-access
-    self._fields[field] = type_checker.CheckValue(new_value)
+    # Testing the value for truthiness captures all of the proto3 defaults
+    # (0, 0.0, enum 0, and False).
+    new_value = type_checker.CheckValue(new_value)
+    if clear_when_set_to_default and not new_value:
+      self._fields.pop(field, None)
+    else:
+      self._fields[field] = new_value
     # Check _cached_byte_size_dirty inline to improve performance, since scalar
     # setters are called frequently.
     if not self._cached_byte_size_dirty:
       self._Modified()
 
-  if field.containing_oneof is not None:
+  if field.containing_oneof:
     def setter(self, new_value):
       field_setter(self, new_value)
       self._UpdateOneofState(field)
@@ -624,24 +644,35 @@
 
   cls.ListFields = ListFields
 
+_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"'
+_Proto2HasError = 'Protocol message has no non-repeated field "%s"'
 
 def _AddHasFieldMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
 
-  singular_fields = {}
+  is_proto3 = (message_descriptor.syntax == "proto3")
+  error_msg = _Proto3HasError if is_proto3 else _Proto2HasError
+
+  hassable_fields = {}
   for field in message_descriptor.fields:
-    if field.label != _FieldDescriptor.LABEL_REPEATED:
-      singular_fields[field.name] = field
-  # Fields inside oneofs are never repeated (enforced by the compiler).
-  for field in message_descriptor.oneofs:
-    singular_fields[field.name] = field
+    if field.label == _FieldDescriptor.LABEL_REPEATED:
+      continue
+    # For proto3, only submessages and fields inside a oneof have presence.
+    if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and
+        not field.containing_oneof):
+      continue
+    hassable_fields[field.name] = field
+
+  if not is_proto3:
+    # Fields inside oneofs are never repeated (enforced by the compiler).
+    for oneof in message_descriptor.oneofs:
+      hassable_fields[oneof.name] = oneof
 
   def HasField(self, field_name):
     try:
-      field = singular_fields[field_name]
+      field = hassable_fields[field_name]
     except KeyError:
-      raise ValueError(
-          'Protocol message has no singular "%s" field.' % field_name)
+      raise ValueError(error_msg % field_name)
 
     if isinstance(field, descriptor_mod.OneofDescriptor):
       try:
@@ -871,6 +902,7 @@
   local_ReadTag = decoder.ReadTag
   local_SkipField = decoder.SkipField
   decoders_by_tag = cls._decoders_by_tag
+  is_proto3 = message_descriptor.syntax == "proto3"
 
   def InternalParse(self, buffer, pos, end):
     self._Modified()
@@ -884,9 +916,11 @@
         new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
         if new_pos == -1:
           return pos
-        if not unknown_field_list:
-          unknown_field_list = self._unknown_fields = []
-        unknown_field_list.append((tag_bytes, buffer[value_start_pos:new_pos]))
+        if not is_proto3:
+          if not unknown_field_list:
+            unknown_field_list = self._unknown_fields = []
+          unknown_field_list.append(
+              (tag_bytes, buffer[value_start_pos:new_pos]))
         pos = new_pos
       else:
         pos = field_decoder(buffer, new_pos, end, self, field_dict)
@@ -1008,6 +1042,8 @@
             # Construct a new object to represent this field.
             field_value = field._default_constructor(self)
             fields[field] = field_value
+            if field.containing_oneof:
+              self._UpdateOneofState(field)
           field_value.MergeFrom(value)
       else:
         self._fields[field] = value
@@ -1252,11 +1288,10 @@
 
     # It's slightly wasteful to lookup the type checker each time,
     # but we expect this to be a vanishingly uncommon case anyway.
-    type_checker = type_checkers.GetTypeChecker(
-        extension_handle)
+    type_checker = type_checkers.GetTypeChecker(extension_handle)
     # pylint: disable=protected-access
     self._extended_message._fields[extension_handle] = (
-      type_checker.CheckValue(value))
+        type_checker.CheckValue(value))
     self._extended_message._Modified()
 
   def _FindExtensionByName(self, name):
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 6b24b09..a62d984 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -1792,6 +1792,17 @@
     # Just check the default value.
     self.assertEqual(57, msg.inner.value)
 
+  @basetest.unittest.skipIf(
+      api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
+      'CPPv2-specific test')
+  def testBadArguments(self):
+    # Some of these assertions used to segfault.
+    from google.protobuf.pyext import _message
+    self.assertRaises(TypeError, _message.Message._GetFieldDescriptor, 3)
+    self.assertRaises(TypeError, _message.Message._GetExtensionDescriptor, 42)
+    self.assertRaises(TypeError,
+                      unittest_pb2.TestAllTypes().__getattribute__, 42)
+
 
 #  Since we had so many tests for protocol buffer equality, we broke these out
 #  into separate TestCase classes.
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index 787f465..d84e383 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -40,13 +40,19 @@
 
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
+from google.protobuf import descriptor_pb2
 
+# Tests whether the given TestAllTypes message is proto2 or not.
+# This is used to gate several fields/features that only exist
+# for the proto2 version of the message.
+def IsProto2(message):
+  return message.DESCRIPTOR.syntax == "proto2"
 
 def SetAllNonLazyFields(message):
   """Sets every non-lazy field in the message to a unique value.
 
   Args:
-    message: A unittest_pb2.TestAllTypes instance.
+    message: A TestAllTypes instance.
   """
 
   #
@@ -77,7 +83,8 @@
 
   message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ
   message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ
-  message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ
+  if IsProto2(message):
+    message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ
 
   message.optional_string_piece = u'124'
   message.optional_cord = u'125'
@@ -110,7 +117,8 @@
 
   message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR)
   message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR)
-  message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR)
+  if IsProto2(message):
+    message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR)
 
   message.repeated_string_piece.append(u'224')
   message.repeated_cord.append(u'225')
@@ -140,7 +148,8 @@
 
   message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ)
   message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ)
-  message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ)
+  if IsProto2(message):
+    message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ)
 
   message.repeated_string_piece.append(u'324')
   message.repeated_cord.append(u'325')
@@ -149,28 +158,29 @@
   # Fields that have defaults.
   #
 
-  message.default_int32 = 401
-  message.default_int64 = 402
-  message.default_uint32 = 403
-  message.default_uint64 = 404
-  message.default_sint32 = 405
-  message.default_sint64 = 406
-  message.default_fixed32 = 407
-  message.default_fixed64 = 408
-  message.default_sfixed32 = 409
-  message.default_sfixed64 = 410
-  message.default_float = 411
-  message.default_double = 412
-  message.default_bool = False
-  message.default_string = '415'
-  message.default_bytes = b'416'
+  if IsProto2(message):
+    message.default_int32 = 401
+    message.default_int64 = 402
+    message.default_uint32 = 403
+    message.default_uint64 = 404
+    message.default_sint32 = 405
+    message.default_sint64 = 406
+    message.default_fixed32 = 407
+    message.default_fixed64 = 408
+    message.default_sfixed32 = 409
+    message.default_sfixed64 = 410
+    message.default_float = 411
+    message.default_double = 412
+    message.default_bool = False
+    message.default_string = '415'
+    message.default_bytes = b'416'
 
-  message.default_nested_enum = unittest_pb2.TestAllTypes.FOO
-  message.default_foreign_enum = unittest_pb2.FOREIGN_FOO
-  message.default_import_enum = unittest_import_pb2.IMPORT_FOO
+    message.default_nested_enum = unittest_pb2.TestAllTypes.FOO
+    message.default_foreign_enum = unittest_pb2.FOREIGN_FOO
+    message.default_import_enum = unittest_import_pb2.IMPORT_FOO
 
-  message.default_string_piece = '424'
-  message.default_cord = '425'
+    message.default_string_piece = '424'
+    message.default_cord = '425'
 
   message.oneof_uint32 = 601
   message.oneof_nested_message.bb = 602
@@ -398,7 +408,8 @@
 
   test_case.assertTrue(message.HasField('optional_nested_enum'))
   test_case.assertTrue(message.HasField('optional_foreign_enum'))
-  test_case.assertTrue(message.HasField('optional_import_enum'))
+  if IsProto2(message):
+    test_case.assertTrue(message.HasField('optional_import_enum'))
 
   test_case.assertTrue(message.HasField('optional_string_piece'))
   test_case.assertTrue(message.HasField('optional_cord'))
@@ -430,8 +441,9 @@
                         message.optional_nested_enum)
   test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
                         message.optional_foreign_enum)
-  test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
-                        message.optional_import_enum)
+  if IsProto2(message):
+    test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+                          message.optional_import_enum)
 
   # -----------------------------------------------------------------
 
@@ -457,7 +469,8 @@
   test_case.assertEqual(2, len(message.repeated_import_message))
   test_case.assertEqual(2, len(message.repeated_nested_enum))
   test_case.assertEqual(2, len(message.repeated_foreign_enum))
-  test_case.assertEqual(2, len(message.repeated_import_enum))
+  if IsProto2(message):
+    test_case.assertEqual(2, len(message.repeated_import_enum))
 
   test_case.assertEqual(2, len(message.repeated_string_piece))
   test_case.assertEqual(2, len(message.repeated_cord))
@@ -488,8 +501,9 @@
                         message.repeated_nested_enum[0])
   test_case.assertEqual(unittest_pb2.FOREIGN_BAR,
                         message.repeated_foreign_enum[0])
-  test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
-                        message.repeated_import_enum[0])
+  if IsProto2(message):
+    test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
+                          message.repeated_import_enum[0])
 
   test_case.assertEqual(301, message.repeated_int32[1])
   test_case.assertEqual(302, message.repeated_int64[1])
@@ -517,53 +531,55 @@
                         message.repeated_nested_enum[1])
   test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
                         message.repeated_foreign_enum[1])
-  test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
-                        message.repeated_import_enum[1])
+  if IsProto2(message):
+    test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+                          message.repeated_import_enum[1])
 
   # -----------------------------------------------------------------
 
-  test_case.assertTrue(message.HasField('default_int32'))
-  test_case.assertTrue(message.HasField('default_int64'))
-  test_case.assertTrue(message.HasField('default_uint32'))
-  test_case.assertTrue(message.HasField('default_uint64'))
-  test_case.assertTrue(message.HasField('default_sint32'))
-  test_case.assertTrue(message.HasField('default_sint64'))
-  test_case.assertTrue(message.HasField('default_fixed32'))
-  test_case.assertTrue(message.HasField('default_fixed64'))
-  test_case.assertTrue(message.HasField('default_sfixed32'))
-  test_case.assertTrue(message.HasField('default_sfixed64'))
-  test_case.assertTrue(message.HasField('default_float'))
-  test_case.assertTrue(message.HasField('default_double'))
-  test_case.assertTrue(message.HasField('default_bool'))
-  test_case.assertTrue(message.HasField('default_string'))
-  test_case.assertTrue(message.HasField('default_bytes'))
+  if IsProto2(message):
+    test_case.assertTrue(message.HasField('default_int32'))
+    test_case.assertTrue(message.HasField('default_int64'))
+    test_case.assertTrue(message.HasField('default_uint32'))
+    test_case.assertTrue(message.HasField('default_uint64'))
+    test_case.assertTrue(message.HasField('default_sint32'))
+    test_case.assertTrue(message.HasField('default_sint64'))
+    test_case.assertTrue(message.HasField('default_fixed32'))
+    test_case.assertTrue(message.HasField('default_fixed64'))
+    test_case.assertTrue(message.HasField('default_sfixed32'))
+    test_case.assertTrue(message.HasField('default_sfixed64'))
+    test_case.assertTrue(message.HasField('default_float'))
+    test_case.assertTrue(message.HasField('default_double'))
+    test_case.assertTrue(message.HasField('default_bool'))
+    test_case.assertTrue(message.HasField('default_string'))
+    test_case.assertTrue(message.HasField('default_bytes'))
 
-  test_case.assertTrue(message.HasField('default_nested_enum'))
-  test_case.assertTrue(message.HasField('default_foreign_enum'))
-  test_case.assertTrue(message.HasField('default_import_enum'))
+    test_case.assertTrue(message.HasField('default_nested_enum'))
+    test_case.assertTrue(message.HasField('default_foreign_enum'))
+    test_case.assertTrue(message.HasField('default_import_enum'))
 
-  test_case.assertEqual(401, message.default_int32)
-  test_case.assertEqual(402, message.default_int64)
-  test_case.assertEqual(403, message.default_uint32)
-  test_case.assertEqual(404, message.default_uint64)
-  test_case.assertEqual(405, message.default_sint32)
-  test_case.assertEqual(406, message.default_sint64)
-  test_case.assertEqual(407, message.default_fixed32)
-  test_case.assertEqual(408, message.default_fixed64)
-  test_case.assertEqual(409, message.default_sfixed32)
-  test_case.assertEqual(410, message.default_sfixed64)
-  test_case.assertEqual(411, message.default_float)
-  test_case.assertEqual(412, message.default_double)
-  test_case.assertEqual(False, message.default_bool)
-  test_case.assertEqual('415', message.default_string)
-  test_case.assertEqual(b'416', message.default_bytes)
+    test_case.assertEqual(401, message.default_int32)
+    test_case.assertEqual(402, message.default_int64)
+    test_case.assertEqual(403, message.default_uint32)
+    test_case.assertEqual(404, message.default_uint64)
+    test_case.assertEqual(405, message.default_sint32)
+    test_case.assertEqual(406, message.default_sint64)
+    test_case.assertEqual(407, message.default_fixed32)
+    test_case.assertEqual(408, message.default_fixed64)
+    test_case.assertEqual(409, message.default_sfixed32)
+    test_case.assertEqual(410, message.default_sfixed64)
+    test_case.assertEqual(411, message.default_float)
+    test_case.assertEqual(412, message.default_double)
+    test_case.assertEqual(False, message.default_bool)
+    test_case.assertEqual('415', message.default_string)
+    test_case.assertEqual(b'416', message.default_bytes)
 
-  test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
-                        message.default_nested_enum)
-  test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
-                        message.default_foreign_enum)
-  test_case.assertEqual(unittest_import_pb2.IMPORT_FOO,
-                        message.default_import_enum)
+    test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
+                          message.default_nested_enum)
+    test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
+                          message.default_foreign_enum)
+    test_case.assertEqual(unittest_import_pb2.IMPORT_FOO,
+                          message.default_import_enum)
 
 
 def GoldenFile(filename):
@@ -594,7 +610,7 @@
   """Sets every field in the message to a unique value.
 
   Args:
-    message: A unittest_pb2.TestPackedTypes instance.
+    message: A TestPackedTypes instance.
   """
   message.packed_int32.extend([601, 701])
   message.packed_int64.extend([602, 702])
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 55e3c2c..7d5813f 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -37,13 +37,17 @@
 import re
 
 from google.apputils import basetest
-from google.protobuf import text_format
+from google.protobuf.internal import _parameterized
+
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
 from google.protobuf.internal import test_util
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_mset_pb2
+from google.protobuf import text_format
 
-class TextFormatTest(basetest.TestCase):
+# Base class with some common functionality.
+class TextFormatBase(basetest.TestCase):
 
   def ReadGolden(self, golden_filename):
     with test_util.GoldenFile(golden_filename) as f:
@@ -57,73 +61,24 @@
   def CompareToGoldenText(self, text, golden_text):
     self.assertMultiLineEqual(text, golden_text)
 
-  def testPrintAllFields(self):
-    message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.CompareToGoldenFile(
-        self.RemoveRedundantZeros(text_format.MessageToString(message)),
-        'text_format_unittest_data_oneof_implemented.txt')
+  def RemoveRedundantZeros(self, text):
+    # Some platforms print 1e+5 as 1e+005.  This is fine, but we need to remove
+    # these zeros in order to match the golden file.
+    text = text.replace('e+0','e+').replace('e+0','e+') \
+               .replace('e-0','e-').replace('e-0','e-')
+    # Floating point fields are printed with .0 suffix even if they are
+    # actualy integer numbers.
+    text = re.compile('\.0$', re.MULTILINE).sub('', text)
+    return text
 
-  def testPrintInIndexOrder(self):
-    message = unittest_pb2.TestFieldOrderings()
-    message.my_string = '115'
-    message.my_int = 101
-    message.my_float = 111
-    message.optional_nested_message.oo = 0
-    message.optional_nested_message.bb = 1
-    self.CompareToGoldenText(
-        self.RemoveRedundantZeros(text_format.MessageToString(
-            message, use_index_order=True)),
-        'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
-        'optional_nested_message {\n  oo: 0\n  bb: 1\n}\n')
-    self.CompareToGoldenText(
-        self.RemoveRedundantZeros(text_format.MessageToString(
-            message)),
-        'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
-        'optional_nested_message {\n  bb: 1\n  oo: 0\n}\n')
 
-  def testPrintAllExtensions(self):
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    self.CompareToGoldenFile(
-        self.RemoveRedundantZeros(text_format.MessageToString(message)),
-        'text_format_unittest_extensions_data.txt')
+@_parameterized.Parameters(
+    (unittest_pb2),
+    (unittest_proto3_arena_pb2))
+class TextFormatTest(TextFormatBase):
 
-  def testPrintAllFieldsPointy(self):
-    message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.CompareToGoldenFile(
-        self.RemoveRedundantZeros(
-            text_format.MessageToString(message, pointy_brackets=True)),
-        'text_format_unittest_data_pointy_oneof.txt')
-
-  def testPrintAllExtensionsPointy(self):
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    self.CompareToGoldenFile(
-        self.RemoveRedundantZeros(text_format.MessageToString(
-            message, pointy_brackets=True)),
-        'text_format_unittest_extensions_data_pointy.txt')
-
-  def testPrintMessageSet(self):
-    message = unittest_mset_pb2.TestMessageSetContainer()
-    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
-    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
-    message.message_set.Extensions[ext1].i = 23
-    message.message_set.Extensions[ext2].str = 'foo'
-    self.CompareToGoldenText(
-        text_format.MessageToString(message),
-        'message_set {\n'
-        '  [protobuf_unittest.TestMessageSetExtension1] {\n'
-        '    i: 23\n'
-        '  }\n'
-        '  [protobuf_unittest.TestMessageSetExtension2] {\n'
-        '    str: \"foo\"\n'
-        '  }\n'
-        '}\n')
-
-  def testPrintExotic(self):
-    message = unittest_pb2.TestAllTypes()
+  def testPrintExotic(self, message_module):
+    message = message_module.TestAllTypes()
     message.repeated_int64.append(-9223372036854775808)
     message.repeated_uint64.append(18446744073709551615)
     message.repeated_double.append(123.456)
@@ -142,61 +97,44 @@
         ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
         'repeated_string: "\\303\\274\\352\\234\\237"\n')
 
-  def testPrintExoticUnicodeSubclass(self):
+  def testPrintExoticUnicodeSubclass(self, message_module):
     class UnicodeSub(unicode):
       pass
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
     message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f'))
     self.CompareToGoldenText(
         text_format.MessageToString(message),
         'repeated_string: "\\303\\274\\352\\234\\237"\n')
 
-  def testPrintNestedMessageAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
+  def testPrintNestedMessageAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
     msg = message.repeated_nested_message.add()
     msg.bb = 42
     self.CompareToGoldenText(
         text_format.MessageToString(message, as_one_line=True),
         'repeated_nested_message { bb: 42 }')
 
-  def testPrintRepeatedFieldsAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
+  def testPrintRepeatedFieldsAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
     message.repeated_int32.append(1)
     message.repeated_int32.append(1)
     message.repeated_int32.append(3)
-    message.repeated_string.append("Google")
-    message.repeated_string.append("Zurich")
+    message.repeated_string.append('Google')
+    message.repeated_string.append('Zurich')
     self.CompareToGoldenText(
         text_format.MessageToString(message, as_one_line=True),
         'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 '
         'repeated_string: "Google" repeated_string: "Zurich"')
 
-  def testPrintNestedNewLineInStringAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
-    message.optional_string = "a\nnew\nline"
+  def testPrintNestedNewLineInStringAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
+    message.optional_string = 'a\nnew\nline'
     self.CompareToGoldenText(
         text_format.MessageToString(message, as_one_line=True),
         'optional_string: "a\\nnew\\nline"')
 
-  def testPrintMessageSetAsOneLine(self):
-    message = unittest_mset_pb2.TestMessageSetContainer()
-    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
-    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
-    message.message_set.Extensions[ext1].i = 23
-    message.message_set.Extensions[ext2].str = 'foo'
-    self.CompareToGoldenText(
-        text_format.MessageToString(message, as_one_line=True),
-        'message_set {'
-        ' [protobuf_unittest.TestMessageSetExtension1] {'
-        ' i: 23'
-        ' }'
-        ' [protobuf_unittest.TestMessageSetExtension2] {'
-        ' str: \"foo\"'
-        ' }'
-        ' }')
-
-  def testPrintExoticAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
+  def testPrintExoticAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
     message.repeated_int64.append(-9223372036854775808)
     message.repeated_uint64.append(18446744073709551615)
     message.repeated_double.append(123.456)
@@ -216,8 +154,8 @@
         '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""'
         ' repeated_string: "\\303\\274\\352\\234\\237"')
 
-  def testRoundTripExoticAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
+  def testRoundTripExoticAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
     message.repeated_int64.append(-9223372036854775808)
     message.repeated_uint64.append(18446744073709551615)
     message.repeated_double.append(123.456)
@@ -229,7 +167,7 @@
     # Test as_utf8 = False.
     wire_text = text_format.MessageToString(
         message, as_one_line=True, as_utf8=False)
-    parsed_message = unittest_pb2.TestAllTypes()
+    parsed_message = message_module.TestAllTypes()
     r = text_format.Parse(wire_text, parsed_message)
     self.assertIs(r, parsed_message)
     self.assertEquals(message, parsed_message)
@@ -237,25 +175,25 @@
     # Test as_utf8 = True.
     wire_text = text_format.MessageToString(
         message, as_one_line=True, as_utf8=True)
-    parsed_message = unittest_pb2.TestAllTypes()
+    parsed_message = message_module.TestAllTypes()
     r = text_format.Parse(wire_text, parsed_message)
     self.assertIs(r, parsed_message)
     self.assertEquals(message, parsed_message,
                       '\n%s != %s' % (message, parsed_message))
 
-  def testPrintRawUtf8String(self):
-    message = unittest_pb2.TestAllTypes()
+  def testPrintRawUtf8String(self, message_module):
+    message = message_module.TestAllTypes()
     message.repeated_string.append(u'\u00fc\ua71f')
     text = text_format.MessageToString(message, as_utf8=True)
     self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n')
-    parsed_message = unittest_pb2.TestAllTypes()
+    parsed_message = message_module.TestAllTypes()
     text_format.Parse(text, parsed_message)
     self.assertEquals(message, parsed_message,
                       '\n%s != %s' % (message, parsed_message))
 
-  def testPrintFloatFormat(self):
+  def testPrintFloatFormat(self, message_module):
     # Check that float_format argument is passed to sub-message formatting.
-    message = unittest_pb2.NestedTestAllTypes()
+    message = message_module.NestedTestAllTypes()
     # We use 1.25 as it is a round number in binary.  The proto 32-bit float
     # will not gain additional imprecise digits as a 64-bit Python float and
     # show up in its str.  32-bit 1.2 is noisy when extended to 64-bit:
@@ -285,85 +223,24 @@
         self.RemoveRedundantZeros(text_message),
         'payload {{ {} {} {} {} }}'.format(*formatted_fields))
 
-  def testMessageToString(self):
-    message = unittest_pb2.ForeignMessage()
+  def testMessageToString(self, message_module):
+    message = message_module.ForeignMessage()
     message.c = 123
     self.assertEqual('c: 123\n', str(message))
 
-  def RemoveRedundantZeros(self, text):
-    # Some platforms print 1e+5 as 1e+005.  This is fine, but we need to remove
-    # these zeros in order to match the golden file.
-    text = text.replace('e+0','e+').replace('e+0','e+') \
-               .replace('e-0','e-').replace('e-0','e-')
-    # Floating point fields are printed with .0 suffix even if they are
-    # actualy integer numbers.
-    text = re.compile('\.0$', re.MULTILINE).sub('', text)
-    return text
-
-  def testParseGolden(self):
-    golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
-    parsed_message = unittest_pb2.TestAllTypes()
-    r = text_format.Parse(golden_text, parsed_message)
-    self.assertIs(r, parsed_message)
-
-    message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.assertEquals(message, parsed_message)
-
-  def testParseGoldenExtensions(self):
-    golden_text = '\n'.join(self.ReadGolden(
-        'text_format_unittest_extensions_data.txt'))
-    parsed_message = unittest_pb2.TestAllExtensions()
-    text_format.Parse(golden_text, parsed_message)
-
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    self.assertEquals(message, parsed_message)
-
-  def testParseAllFields(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseAllFields(self, message_module):
+    message = message_module.TestAllTypes()
     test_util.SetAllFields(message)
     ascii_text = text_format.MessageToString(message)
 
-    parsed_message = unittest_pb2.TestAllTypes()
+    parsed_message = message_module.TestAllTypes()
     text_format.Parse(ascii_text, parsed_message)
     self.assertEqual(message, parsed_message)
-    test_util.ExpectAllFieldsSet(self, message)
+    if message_module is unittest_pb2:
+      test_util.ExpectAllFieldsSet(self, message)
 
-  def testParseAllExtensions(self):
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    ascii_text = text_format.MessageToString(message)
-
-    parsed_message = unittest_pb2.TestAllExtensions()
-    text_format.Parse(ascii_text, parsed_message)
-    self.assertEqual(message, parsed_message)
-
-  def testParseMessageSet(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ('repeated_uint64: 1\n'
-            'repeated_uint64: 2\n')
-    text_format.Parse(text, message)
-    self.assertEqual(1, message.repeated_uint64[0])
-    self.assertEqual(2, message.repeated_uint64[1])
-
-    message = unittest_mset_pb2.TestMessageSetContainer()
-    text = ('message_set {\n'
-            '  [protobuf_unittest.TestMessageSetExtension1] {\n'
-            '    i: 23\n'
-            '  }\n'
-            '  [protobuf_unittest.TestMessageSetExtension2] {\n'
-            '    str: \"foo\"\n'
-            '  }\n'
-            '}\n')
-    text_format.Parse(text, message)
-    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
-    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
-    self.assertEquals(23, message.message_set.Extensions[ext1].i)
-    self.assertEquals('foo', message.message_set.Extensions[ext2].str)
-
-  def testParseExotic(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseExotic(self, message_module):
+    message = message_module.TestAllTypes()
     text = ('repeated_int64: -9223372036854775808\n'
             'repeated_uint64: 18446744073709551615\n'
             'repeated_double: 123.456\n'
@@ -388,8 +265,8 @@
     self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2])
     self.assertEqual(u'\u00fc', message.repeated_string[3])
 
-  def testParseTrailingCommas(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseTrailingCommas(self, message_module):
+    message = message_module.TestAllTypes()
     text = ('repeated_int64: 100;\n'
             'repeated_int64: 200;\n'
             'repeated_int64: 300,\n'
@@ -403,51 +280,37 @@
     self.assertEqual(u'one', message.repeated_string[0])
     self.assertEqual(u'two', message.repeated_string[1])
 
-  def testParseEmptyText(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseEmptyText(self, message_module):
+    message = message_module.TestAllTypes()
     text = ''
     text_format.Parse(text, message)
-    self.assertEquals(unittest_pb2.TestAllTypes(), message)
+    self.assertEquals(message_module.TestAllTypes(), message)
 
-  def testParseInvalidUtf8(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseInvalidUtf8(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'repeated_string: "\\xc3\\xc3"'
     self.assertRaises(text_format.ParseError, text_format.Parse, text, message)
 
-  def testParseSingleWord(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseSingleWord(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'foo'
-    self.assertRaisesWithLiteralMatch(
+    self.assertRaisesRegexp(
         text_format.ParseError,
-        ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
-         '"foo".'),
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"foo".'),
         text_format.Parse, text, message)
 
-  def testParseUnknownField(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseUnknownField(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'unknown_field: 8\n'
-    self.assertRaisesWithLiteralMatch(
+    self.assertRaisesRegexp(
         text_format.ParseError,
-        ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
-         '"unknown_field".'),
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"unknown_field".'),
         text_format.Parse, text, message)
 
-  def testParseBadExtension(self):
-    message = unittest_pb2.TestAllExtensions()
-    text = '[unknown_extension]: 8\n'
-    self.assertRaisesWithLiteralMatch(
-        text_format.ParseError,
-        '1:2 : Extension "unknown_extension" not registered.',
-        text_format.Parse, text, message)
-    message = unittest_pb2.TestAllTypes()
-    self.assertRaisesWithLiteralMatch(
-        text_format.ParseError,
-        ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
-         'extensions.'),
-        text_format.Parse, text, message)
-
-  def testParseGroupNotClosed(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseGroupNotClosed(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'RepeatedGroup: <'
     self.assertRaisesWithLiteralMatch(
         text_format.ParseError, '1:16 : Expected ">".',
@@ -458,46 +321,46 @@
         text_format.ParseError, '1:16 : Expected "}".',
         text_format.Parse, text, message)
 
-  def testParseEmptyGroup(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseEmptyGroup(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'OptionalGroup: {}'
     text_format.Parse(text, message)
     self.assertTrue(message.HasField('optionalgroup'))
 
     message.Clear()
 
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
     text = 'OptionalGroup: <>'
     text_format.Parse(text, message)
     self.assertTrue(message.HasField('optionalgroup'))
 
-  def testParseBadEnumValue(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseBadEnumValue(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'optional_nested_enum: BARR'
-    self.assertRaisesWithLiteralMatch(
+    self.assertRaisesRegexp(
         text_format.ParseError,
-        ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
-         'has no value named BARR.'),
+        (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
+         r'has no value named BARR.'),
         text_format.Parse, text, message)
 
-    message = unittest_pb2.TestAllTypes()
+    message = message_module.TestAllTypes()
     text = 'optional_nested_enum: 100'
-    self.assertRaisesWithLiteralMatch(
+    self.assertRaisesRegexp(
         text_format.ParseError,
-        ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
-         'has no value with number 100.'),
+        (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
+         r'has no value with number 100.'),
         text_format.Parse, text, message)
 
-  def testParseBadIntValue(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseBadIntValue(self, message_module):
+    message = message_module.TestAllTypes()
     text = 'optional_int32: bork'
     self.assertRaisesWithLiteralMatch(
         text_format.ParseError,
         ('1:17 : Couldn\'t parse integer: bork'),
         text_format.Parse, text, message)
 
-  def testParseStringFieldUnescape(self):
-    message = unittest_pb2.TestAllTypes()
+  def testParseStringFieldUnescape(self, message_module):
+    message = message_module.TestAllTypes()
     text = r'''repeated_string: "\xf\x62"
                repeated_string: "\\xf\\x62"
                repeated_string: "\\\xf\\\x62"
@@ -516,40 +379,205 @@
                      message.repeated_string[4])
     self.assertEqual(SLASH + 'x20', message.repeated_string[5])
 
-  def testMergeDuplicateScalars(self):
-    message = unittest_pb2.TestAllTypes()
+  def testMergeDuplicateScalars(self, message_module):
+    message = message_module.TestAllTypes()
     text = ('optional_int32: 42 '
             'optional_int32: 67')
     r = text_format.Merge(text, message)
     self.assertIs(r, message)
     self.assertEqual(67, message.optional_int32)
 
-  def testParseDuplicateScalars(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ('optional_int32: 42 '
-            'optional_int32: 67')
-    self.assertRaisesWithLiteralMatch(
-        text_format.ParseError,
-        ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
-         'have multiple "optional_int32" fields.'),
-        text_format.Parse, text, message)
-
-  def testMergeDuplicateNestedMessageScalars(self):
-    message = unittest_pb2.TestAllTypes()
+  def testMergeDuplicateNestedMessageScalars(self, message_module):
+    message = message_module.TestAllTypes()
     text = ('optional_nested_message { bb: 1 } '
             'optional_nested_message { bb: 2 }')
     r = text_format.Merge(text, message)
     self.assertTrue(r is message)
     self.assertEqual(2, message.optional_nested_message.bb)
 
-  def testParseDuplicateNestedMessageScalars(self):
+  def testParseOneof(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m2 = message_module.TestAllTypes()
+    text_format.Parse(text_format.MessageToString(m), m2)
+    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+
+# These are tests that aren't fundamentally specific to proto2, but are at
+# the moment because of differences between the proto2 and proto3 test schemas.
+# Ideally the schemas would be made more similar so these tests could pass.
+class OnlyWorksWithProto2RightNowTests(TextFormatBase):
+
+  def testParseGolden(self):
+    golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
+    parsed_message = unittest_pb2.TestAllTypes()
+    r = text_format.Parse(golden_text, parsed_message)
+    self.assertIs(r, parsed_message)
+
     message = unittest_pb2.TestAllTypes()
-    text = ('optional_nested_message { bb: 1 } '
-            'optional_nested_message { bb: 2 }')
+    test_util.SetAllFields(message)
+    self.assertEquals(message, parsed_message)
+
+  def testPrintAllFields(self):
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(text_format.MessageToString(message)),
+        'text_format_unittest_data_oneof_implemented.txt')
+
+  def testPrintAllFieldsPointy(self):
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(
+            text_format.MessageToString(message, pointy_brackets=True)),
+        'text_format_unittest_data_pointy_oneof.txt')
+
+  def testPrintInIndexOrder(self):
+    message = unittest_pb2.TestFieldOrderings()
+    message.my_string = '115'
+    message.my_int = 101
+    message.my_float = 111
+    message.optional_nested_message.oo = 0
+    message.optional_nested_message.bb = 1
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_format.MessageToString(
+            message, use_index_order=True)),
+        'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
+        'optional_nested_message {\n  oo: 0\n  bb: 1\n}\n')
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_format.MessageToString(
+            message)),
+        'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
+        'optional_nested_message {\n  bb: 1\n  oo: 0\n}\n')
+
+  def testMergeLinesGolden(self):
+    opened = self.ReadGolden('text_format_unittest_data.txt')
+    parsed_message = unittest_pb2.TestAllTypes()
+    r = text_format.MergeLines(opened, parsed_message)
+    self.assertIs(r, parsed_message)
+
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.assertEqual(message, parsed_message)
+
+  def testParseLinesGolden(self):
+    opened = self.ReadGolden('text_format_unittest_data.txt')
+    parsed_message = unittest_pb2.TestAllTypes()
+    r = text_format.ParseLines(opened, parsed_message)
+    self.assertIs(r, parsed_message)
+
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.assertEquals(message, parsed_message)
+
+
+# Tests of proto2-only features (MessageSet and extensions).
+class Proto2Tests(TextFormatBase):
+
+  def testPrintMessageSet(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        'message_set {\n'
+        '  [protobuf_unittest.TestMessageSetExtension1] {\n'
+        '    i: 23\n'
+        '  }\n'
+        '  [protobuf_unittest.TestMessageSetExtension2] {\n'
+        '    str: \"foo\"\n'
+        '  }\n'
+        '}\n')
+
+  def testPrintMessageSetAsOneLine(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'message_set {'
+        ' [protobuf_unittest.TestMessageSetExtension1] {'
+        ' i: 23'
+        ' }'
+        ' [protobuf_unittest.TestMessageSetExtension2] {'
+        ' str: \"foo\"'
+        ' }'
+        ' }')
+
+  def testParseMessageSet(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('repeated_uint64: 1\n'
+            'repeated_uint64: 2\n')
+    text_format.Parse(text, message)
+    self.assertEqual(1, message.repeated_uint64[0])
+    self.assertEqual(2, message.repeated_uint64[1])
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    text = ('message_set {\n'
+            '  [protobuf_unittest.TestMessageSetExtension1] {\n'
+            '    i: 23\n'
+            '  }\n'
+            '  [protobuf_unittest.TestMessageSetExtension2] {\n'
+            '    str: \"foo\"\n'
+            '  }\n'
+            '}\n')
+    text_format.Parse(text, message)
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    self.assertEquals(23, message.message_set.Extensions[ext1].i)
+    self.assertEquals('foo', message.message_set.Extensions[ext2].str)
+
+  def testPrintAllExtensions(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(text_format.MessageToString(message)),
+        'text_format_unittest_extensions_data.txt')
+
+  def testPrintAllExtensionsPointy(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(text_format.MessageToString(
+            message, pointy_brackets=True)),
+        'text_format_unittest_extensions_data_pointy.txt')
+
+  def testParseGoldenExtensions(self):
+    golden_text = '\n'.join(self.ReadGolden(
+        'text_format_unittest_extensions_data.txt'))
+    parsed_message = unittest_pb2.TestAllExtensions()
+    text_format.Parse(golden_text, parsed_message)
+
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.assertEquals(message, parsed_message)
+
+  def testParseAllExtensions(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    ascii_text = text_format.MessageToString(message)
+
+    parsed_message = unittest_pb2.TestAllExtensions()
+    text_format.Parse(ascii_text, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def testParseBadExtension(self):
+    message = unittest_pb2.TestAllExtensions()
+    text = '[unknown_extension]: 8\n'
     self.assertRaisesWithLiteralMatch(
         text_format.ParseError,
-        ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
-         'should not have multiple "bb" fields.'),
+        '1:2 : Extension "unknown_extension" not registered.',
+        text_format.Parse, text, message)
+    message = unittest_pb2.TestAllTypes()
+    self.assertRaisesWithLiteralMatch(
+        text_format.ParseError,
+        ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
+         'extensions.'),
         text_format.Parse, text, message)
 
   def testMergeDuplicateExtensionScalars(self):
@@ -572,32 +600,25 @@
          '"protobuf_unittest.optional_int32_extension" extensions.'),
         text_format.Parse, text, message)
 
-  def testParseLinesGolden(self):
-    opened = self.ReadGolden('text_format_unittest_data.txt')
-    parsed_message = unittest_pb2.TestAllTypes()
-    r = text_format.ParseLines(opened, parsed_message)
-    self.assertIs(r, parsed_message)
-
+  def testParseDuplicateNestedMessageScalars(self):
     message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.assertEquals(message, parsed_message)
+    text = ('optional_nested_message { bb: 1 } '
+            'optional_nested_message { bb: 2 }')
+    self.assertRaisesWithLiteralMatch(
+        text_format.ParseError,
+        ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
+         'should not have multiple "bb" fields.'),
+        text_format.Parse, text, message)
 
-  def testMergeLinesGolden(self):
-    opened = self.ReadGolden('text_format_unittest_data.txt')
-    parsed_message = unittest_pb2.TestAllTypes()
-    r = text_format.MergeLines(opened, parsed_message)
-    self.assertIs(r, parsed_message)
-
+  def testParseDuplicateScalars(self):
     message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.assertEqual(message, parsed_message)
-
-  def testParseOneof(self):
-    m = unittest_pb2.TestAllTypes()
-    m.oneof_uint32 = 11
-    m2 = unittest_pb2.TestAllTypes()
-    text_format.Parse(text_format.MessageToString(m), m2)
-    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+    text = ('optional_int32: 42 '
+            'optional_int32: 67')
+    self.assertRaisesWithLiteralMatch(
+        text_format.ParseError,
+        ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
+         'have multiple "optional_int32" fields.'),
+        text_format.Parse, text, message)
 
 
 class TokenizerTest(basetest.TestCase):
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index 118725d..76c056c 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -59,6 +59,8 @@
 
 _FieldDescriptor = descriptor.FieldDescriptor
 
+def SupportsOpenEnums(field_descriptor):
+  return field_descriptor.containing_type.syntax == "proto3"
 
 def GetTypeChecker(field):
   """Returns a type checker for a message field of the specified types.
@@ -74,7 +76,11 @@
       field.type == _FieldDescriptor.TYPE_STRING):
     return UnicodeValueChecker()
   if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
-    return EnumValueChecker(field.enum_type)
+    if SupportsOpenEnums(field):
+      # When open enums are supported, any int32 can be assigned.
+      return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32]
+    else:
+      return EnumValueChecker(field.enum_type)
   return _VALUE_CHECKERS[field.cpp_type]
 
 
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index a4dc1f7..59f9ae4 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -38,6 +38,7 @@
 from google.apputils import basetest
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
 from google.protobuf.internal import encoder
 from google.protobuf.internal import missing_enum_values_pb2
@@ -45,10 +46,81 @@
 from google.protobuf.internal import type_checkers
 
 
+class UnknownFieldsTest(basetest.TestCase):
+
+  def setUp(self):
+    self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.all_fields = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(self.all_fields)
+    self.all_fields_data = self.all_fields.SerializeToString()
+    self.empty_message = unittest_pb2.TestEmptyMessage()
+    self.empty_message.ParseFromString(self.all_fields_data)
+
+  def testSerialize(self):
+    data = self.empty_message.SerializeToString()
+
+    # Don't use assertEqual because we don't want to dump raw binary data to
+    # stdout.
+    self.assertTrue(data == self.all_fields_data)
+
+  def testSerializeProto3(self):
+    # Verify that proto3 doesn't preserve unknown fields.
+    message = unittest_proto3_arena_pb2.TestEmptyMessage()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(0, len(message.SerializeToString()))
+
+  def testByteSize(self):
+    self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
+
+  def testListFields(self):
+    # Make sure ListFields doesn't return unknown fields.
+    self.assertEqual(0, len(self.empty_message.ListFields()))
+
+  def testSerializeMessageSetWireFormatUnknownExtension(self):
+    # Create a message using the message set wire format with an unknown
+    # message.
+    raw = unittest_mset_pb2.RawMessageSet()
+
+    # Add an unknown extension.
+    item = raw.item.add()
+    item.type_id = 1545009
+    message1 = unittest_mset_pb2.TestMessageSetExtension1()
+    message1.i = 12345
+    item.message = message1.SerializeToString()
+
+    serialized = raw.SerializeToString()
+
+    # Parse message using the message set wire format.
+    proto = unittest_mset_pb2.TestMessageSet()
+    proto.MergeFromString(serialized)
+
+    # Verify that the unknown extension is serialized unchanged
+    reserialized = proto.SerializeToString()
+    new_raw = unittest_mset_pb2.RawMessageSet()
+    new_raw.MergeFromString(reserialized)
+    self.assertEqual(raw, new_raw)
+
+  # C++ implementation for proto2 does not currently take into account unknown
+  # fields when checking equality.
+  #
+  # TODO(haberman): fix this.
+  @basetest.unittest.skipIf(
+      api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+      'C++ implementation does not expose unknown fields to Python')
+  def testEquals(self):
+    message = unittest_pb2.TestEmptyMessage()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(self.empty_message, message)
+
+    self.all_fields.ClearField('optional_string')
+    message.ParseFromString(self.all_fields.SerializeToString())
+    self.assertNotEqual(self.empty_message, message)
+
+
 @basetest.unittest.skipIf(
     api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
     'C++ implementation does not expose unknown fields to Python')
-class UnknownFieldsTest(basetest.TestCase):
+class UnknownFieldsAccessorsTest(basetest.TestCase):
 
   def setUp(self):
     self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
@@ -98,13 +170,6 @@
     value = self.GetField('optionalgroup')
     self.assertEqual(self.all_fields.optionalgroup, value)
 
-  def testSerialize(self):
-    data = self.empty_message.SerializeToString()
-
-    # Don't use assertEqual because we don't want to dump raw binary data to
-    # stdout.
-    self.assertTrue(data == self.all_fields_data)
-
   def testCopyFrom(self):
     message = unittest_pb2.TestEmptyMessage()
     message.CopyFrom(self.empty_message)
@@ -132,51 +197,12 @@
     self.empty_message.Clear()
     self.assertEqual(0, len(self.empty_message._unknown_fields))
 
-  def testByteSize(self):
-    self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
-
   def testUnknownExtensions(self):
     message = unittest_pb2.TestEmptyMessageWithExtensions()
     message.ParseFromString(self.all_fields_data)
     self.assertEqual(self.empty_message._unknown_fields,
                      message._unknown_fields)
 
-  def testListFields(self):
-    # Make sure ListFields doesn't return unknown fields.
-    self.assertEqual(0, len(self.empty_message.ListFields()))
-
-  def testSerializeMessageSetWireFormatUnknownExtension(self):
-    # Create a message using the message set wire format with an unknown
-    # message.
-    raw = unittest_mset_pb2.RawMessageSet()
-
-    # Add an unknown extension.
-    item = raw.item.add()
-    item.type_id = 1545009
-    message1 = unittest_mset_pb2.TestMessageSetExtension1()
-    message1.i = 12345
-    item.message = message1.SerializeToString()
-
-    serialized = raw.SerializeToString()
-
-    # Parse message using the message set wire format.
-    proto = unittest_mset_pb2.TestMessageSet()
-    proto.MergeFromString(serialized)
-
-    # Verify that the unknown extension is serialized unchanged
-    reserialized = proto.SerializeToString()
-    new_raw = unittest_mset_pb2.RawMessageSet()
-    new_raw.MergeFromString(reserialized)
-    self.assertEqual(raw, new_raw)
-
-  def testEquals(self):
-    message = unittest_pb2.TestEmptyMessage()
-    message.ParseFromString(self.all_fields_data)
-    self.assertEqual(self.empty_message, message)
-
-    self.all_fields.ClearField('optional_string')
-    message.ParseFromString(self.all_fields.SerializeToString())
-    self.assertNotEqual(self.empty_message, message)
 
 
 @basetest.unittest.skipIf(
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index 88ed9f4..de2f569 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -36,7 +36,6 @@
 
 __author__ = 'robinson@google.com (Will Robinson)'
 
-
 class Error(Exception): pass
 class DecodeError(Error): pass
 class EncodeError(Error): pass
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 7343c0b..e77d0bb 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -31,10 +31,15 @@
 // Author: petar@google.com (Petar Petrov)
 
 #include <Python.h>
+#include <frameobject.h>
 #include <string>
 
+#include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_containers.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
 
@@ -42,19 +47,97 @@
 
 #if PY_MAJOR_VERSION >= 3
   #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #define PyString_Check PyUnicode_Check
+  #define PyString_InternFromString PyUnicode_InternFromString
   #define PyInt_FromLong PyLong_FromLong
+  #define PyInt_FromSize_t PyLong_FromSize_t
   #if PY_VERSION_HEX < 0x03030000
     #error "Python 3.0 - 3.2 are not supported."
-  #else
-  #define PyString_AsString(ob) \
-    (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
   #endif
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
 #endif
 
 namespace google {
 namespace protobuf {
 namespace python {
 
+PyObject* PyString_FromCppString(const string& str) {
+  return PyString_FromStringAndSize(str.c_str(), str.size());
+}
+
+// Check that the calling Python code is the global scope of a _pb2.py module.
+// This function is used to support the current code generated by the proto
+// compiler, which creates descriptors, then update some properties.
+// For example:
+//   message_descriptor = Descriptor(
+//       name='Message',
+//       fields = [FieldDescriptor(name='field')]
+//   message_descriptor.fields[0].containing_type = message_descriptor
+//
+// This code is still executed, but the descriptors now have no other storage
+// than the (const) C++ pointer, and are immutable.
+// So we let this code pass, by simply ignoring the new value.
+//
+// From user code, descriptors still look immutable.
+//
+// TODO(amauryfa): Change the proto2 compiler to remove the assignments, and
+// remove this hack.
+bool _CalledFromGeneratedFile(int stacklevel) {
+  PyThreadState *state = PyThreadState_GET();
+  if (state == NULL) {
+    return false;
+  }
+  PyFrameObject* frame = state->frame;
+  if (frame == NULL) {
+    return false;
+  }
+  while (stacklevel-- > 0) {
+    frame = frame->f_back;
+    if (frame == NULL) {
+      return false;
+    }
+  }
+  if (frame->f_globals != frame->f_locals) {
+    // Not at global module scope
+    return false;
+  }
+
+  if (frame->f_code->co_filename == NULL) {
+    return false;
+  }
+  char* filename;
+  Py_ssize_t filename_size;
+  if (PyString_AsStringAndSize(frame->f_code->co_filename,
+                               &filename, &filename_size) < 0) {
+    // filename is not a string.
+    PyErr_Clear();
+    return false;
+  }
+  if (filename_size < 7) {
+    // filename is too short.
+    return false;
+  }
+  if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) {
+    // Filename is not ending with _pb2.
+    return false;
+  }
+  return true;
+}
+
+// If the calling code is not a _pb2.py file, raise AttributeError.
+// To be used in attribute setters.
+static int CheckCalledFromGeneratedFile(const char* attr_name) {
+  if (_CalledFromGeneratedFile(0)) {
+    return 0;
+  }
+  PyErr_Format(PyExc_AttributeError,
+               "attribute is not writable: %s", attr_name);
+  return -1;
+}
+
 
 #ifndef PyVarObject_HEAD_INIT
 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@@ -64,42 +147,417 @@
 #endif
 
 
-static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
+// Helper functions for descriptor objects.
 
-namespace cmessage_descriptor {
+// Converts options into a Python protobuf, and cache the result.
+//
+// This is a bit tricky because options can contain extension fields defined in
+// the same proto file. In this case the options parsed from the serialized_pb
+// have unkown fields, and we need to parse them again.
+//
+// Always returns a new reference.
+template<class DescriptorClass>
+static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
+  hash_map<const void*, PyObject*>* descriptor_options =
+      GetDescriptorPool()->descriptor_options;
+  // First search in the cache.
+  if (descriptor_options->find(descriptor) != descriptor_options->end()) {
+    PyObject *value = (*descriptor_options)[descriptor];
+    Py_INCREF(value);
+    return value;
+  }
 
-static void Dealloc(CMessageDescriptor* self) {
+  // Build the Options object: get its Python class, and make a copy of the C++
+  // read-only instance.
+  const Message& options(descriptor->options());
+  const Descriptor *message_type = options.GetDescriptor();
+  PyObject* message_class(cdescriptor_pool::GetMessageClass(
+      GetDescriptorPool(), message_type));
+  if (message_class == NULL) {
+    PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
+                 message_type->full_name().c_str());
+    return NULL;
+  }
+  ScopedPyObjectPtr value(PyEval_CallObject(message_class, NULL));
+  if (value == NULL) {
+    return NULL;
+  }
+  CMessage* cmsg = reinterpret_cast<CMessage*>(value.get());
+
+  const Reflection* reflection = options.GetReflection();
+  const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(options));
+  if (unknown_fields.empty()) {
+    cmsg->message->CopyFrom(options);
+  } else {
+    // Reparse options string!  XXX call cmessage::MergeFromString
+    string serialized;
+    options.SerializeToString(&serialized);
+    io::CodedInputStream input(
+        reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
+    input.SetExtensionRegistry(GetDescriptorPool()->pool,
+                               cmessage::GetMessageFactory());
+    bool success = cmsg->message->MergePartialFromCodedStream(&input);
+    if (!success) {
+      PyErr_Format(PyExc_ValueError, "Error parsing Options message");
+      return NULL;
+    }
+  }
+
+  // Cache the result.
+  Py_INCREF(value);
+  (*GetDescriptorPool()->descriptor_options)[descriptor] = value.get();
+
+  return value.release();
+}
+
+// Copy the C++ descriptor to a Python message.
+// The Python message is an instance of descriptor_pb2.DescriptorProto
+// or similar.
+template<class DescriptorProtoClass, class DescriptorClass>
+static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
+                                   PyObject *target) {
+  const Descriptor* self_descriptor =
+      DescriptorProtoClass::default_instance().GetDescriptor();
+  CMessage* message = reinterpret_cast<CMessage*>(target);
+  if (!PyObject_TypeCheck(target, &CMessage_Type) ||
+      message->message->GetDescriptor() != self_descriptor) {
+    PyErr_Format(PyExc_TypeError, "Not a %s message",
+                 self_descriptor->full_name().c_str());
+    return NULL;
+  }
+  cmessage::AssureWritable(message);
+  DescriptorProtoClass* descriptor_message =
+      static_cast<DescriptorProtoClass*>(message->message);
+  descriptor->CopyTo(descriptor_message);
+  Py_RETURN_NONE;
+}
+
+// All Descriptors classes share the same memory layout.
+typedef struct PyBaseDescriptor {
+  PyObject_HEAD
+
+  // Pointer to the C++ proto2 descriptor.
+  // Like all descriptors, it is owned by the global DescriptorPool.
+  const void* descriptor;
+} PyBaseDescriptor;
+
+
+// FileDescriptor structure "inherits" from the base descriptor.
+typedef struct PyFileDescriptor {
+  PyBaseDescriptor base;
+
+  // The cached version of serialized pb. Either NULL, or a Bytes string.
+  // We own the reference.
+  PyObject *serialized_pb;
+} PyFileDescriptor;
+
+
+namespace descriptor {
+
+// Creates or retrieve a Python descriptor of the specified type.
+// Objects are interned: the same descriptor will return the same object if it
+// was kept alive.
+// Always return a new reference.
+PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) {
+  if (descriptor == NULL) {
+    PyErr_BadInternalCall();
+    return NULL;
+  }
+
+  // See if the object is in the map of interned descriptors
+  hash_map<const void*, PyObject*>::iterator it =
+      GetDescriptorPool()->interned_descriptors->find(descriptor);
+  if (it != GetDescriptorPool()->interned_descriptors->end()) {
+    GOOGLE_DCHECK(Py_TYPE(it->second) == type);
+    Py_INCREF(it->second);
+    return it->second;
+  }
+  // Create a new descriptor object
+  PyBaseDescriptor* py_descriptor = PyObject_New(
+      PyBaseDescriptor, type);
+  if (py_descriptor == NULL) {
+    return NULL;
+  }
+  py_descriptor->descriptor = descriptor;
+  // and cache it.
+  GetDescriptorPool()->interned_descriptors->insert(
+      std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
+
+  return reinterpret_cast<PyObject*>(py_descriptor);
+}
+
+static void Dealloc(PyBaseDescriptor* self) {
+  // Remove from interned dictionary
+  GetDescriptorPool()->interned_descriptors->erase(self->descriptor);
   Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
 }
 
-static PyObject* GetFullName(CMessageDescriptor* self, void *closure) {
-  return PyString_FromStringAndSize(
-      self->descriptor->full_name().c_str(),
-      self->descriptor->full_name().size());
-}
-
-static PyObject* GetName(CMessageDescriptor *self, void *closure) {
-  return PyString_FromStringAndSize(
-      self->descriptor->name().c_str(),
-      self->descriptor->name().size());
-}
-
 static PyGetSetDef Getters[] = {
-  { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
-  { C("name"), (getter)GetName, NULL, "Unqualified name", NULL},
   {NULL}
 };
 
-}  // namespace cmessage_descriptor
-
-PyTypeObject CMessageDescriptor_Type = {
+PyTypeObject PyBaseDescriptor_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  C("google.protobuf.internal."
-    "_net_proto2___python."
-    "CMessageDescriptor"),              // tp_name
-  sizeof(CMessageDescriptor),           // tp_basicsize
+  // Keep the fully qualified _message symbol in a line for opensource.
+  "google.protobuf.internal._message."
+  "DescriptorBase",                     // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
   0,                                    // tp_itemsize
-  (destructor)cmessage_descriptor::Dealloc,  // tp_dealloc
+  (destructor)Dealloc,                  // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "Descriptors base class",             // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  Getters,                              // tp_getset
+};
+
+}  // namespace descriptor
+
+const void* PyDescriptor_AsVoidPtr(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor;
+}
+
+namespace message_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) {
+  return reinterpret_cast<const Descriptor*>(self->descriptor);
+}
+
+static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+  return PyFileDescriptor_New(_GetDescriptor(self)->file());
+}
+
+static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
+  PyObject* concrete_class(cdescriptor_pool::GetMessageClass(
+      GetDescriptorPool(), _GetDescriptor(self)));
+  Py_XINCREF(concrete_class);
+  return concrete_class;
+}
+
+static int SetConcreteClass(PyBaseDescriptor *self, PyObject *value,
+                            void *closure) {
+  // This attribute is also set from reflection.py. Check that it's actually a
+  // no-op.
+  if (value != cdescriptor_pool::GetMessageClass(
+          GetDescriptorPool(), _GetDescriptor(self))) {
+    PyErr_SetString(PyExc_AttributeError, "Cannot change _concrete_class");
+  }
+  return 0;
+}
+
+static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageFieldsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) {
+  return NewMessageFieldsByNumber(_GetDescriptor(self));
+}
+
+static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageFieldsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageNestedTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageNestedTypesSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageExtensionsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) {
+  return NewMessageExtensionsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageEnumsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageEnumsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageEnumValuesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageOneofsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageOneofsSeq(_GetDescriptor(self));
+}
+
+static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) {
+  if (_GetDescriptor(self)->extension_range_count() > 0) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+
+static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* descriptor = _GetDescriptor(self);
+  PyObject* range_list = PyList_New(descriptor->extension_range_count());
+
+  for (int i = 0; i < descriptor->extension_range_count(); i++) {
+    const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
+    PyObject* start = PyInt_FromLong(range->start);
+    PyObject* end = PyInt_FromLong(range->end);
+    PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
+  }
+
+  return range_list;
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_New(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("containing_type");
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const MessageOptions& options(_GetDescriptor(self)->options());
+  if (&options != &MessageOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
+  return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) {
+  const char *enum_name;
+  int number;
+  if (!PyArg_ParseTuple(args, "si", &enum_name, &number))
+    return NULL;
+  const EnumDescriptor *enum_type =
+      _GetDescriptor(self)->FindEnumTypeByName(enum_name);
+  if (enum_type == NULL) {
+    PyErr_SetString(PyExc_KeyError, enum_name);
+    return NULL;
+  }
+  const EnumValueDescriptor *enum_value =
+      enum_type->FindValueByNumber(number);
+  if (enum_value == NULL) {
+    PyErr_Format(PyExc_KeyError, "%d", number);
+    return NULL;
+  }
+  return PyString_FromCppString(enum_value->name());
+}
+
+static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
+  return PyString_InternFromString(
+      FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax()));
+}
+
+static PyGetSetDef Getters[] = {
+  { C("name"), (getter)GetName, NULL, "Last name", NULL},
+  { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
+  { C("_concrete_class"), (getter)GetConcreteClass, (setter)SetConcreteClass, "concrete class", NULL},
+  { C("file"), (getter)GetFile, NULL, "File descriptor", NULL},
+
+  { C("fields"), (getter)GetFieldsSeq, NULL, "Fields sequence", NULL},
+  { C("fields_by_name"), (getter)GetFieldsByName, NULL, "Fields by name", NULL},
+  { C("fields_by_number"), (getter)GetFieldsByNumber, NULL, "Fields by number", NULL},
+  { C("nested_types"), (getter)GetNestedTypesSeq, NULL, "Nested types sequence", NULL},
+  { C("nested_types_by_name"), (getter)GetNestedTypesByName, NULL, "Nested types by name", NULL},
+  { C("extensions"), (getter)GetExtensions, NULL, "Extensions Sequence", NULL},
+  { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL},
+  { C("extension_ranges"), (getter)GetExtensionRanges, NULL, "Extension ranges", NULL},
+  { C("enum_types"), (getter)GetEnumsSeq, NULL, "Enum sequence", NULL},
+  { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enum types by name", NULL},
+  { C("enum_values_by_name"), (getter)GetEnumValuesByName, NULL, "Enum values by name", NULL},
+  { C("oneofs_by_name"), (getter)GetOneofsByName, NULL, "Oneofs by name", NULL},
+  { C("oneofs"), (getter)GetOneofsSeq, NULL, "Oneofs by name", NULL},
+  { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL},
+  { C("is_extendable"), (getter)IsExtendable, (setter)NULL, NULL, NULL},
+  { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
+  { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+  { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+  { "EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS, },
+  {NULL}
+};
+
+}  // namespace message_descriptor
+
+PyTypeObject PyMessageDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  // Keep the fully qualified _message symbol in a line for opensource.
+  C("google.protobuf.internal._message."
+    "MessageDescriptor"),      // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
   0,                                    // tp_print
   0,                                    // tp_getattr
   0,                                    // tp_setattr
@@ -122,70 +580,266 @@
   0,                                    // tp_weaklistoffset
   0,                                    // tp_iter
   0,                                    // tp_iternext
-  0,                                    // tp_methods
+  message_descriptor::Methods,          // tp_methods
   0,                                    // tp_members
-  cmessage_descriptor::Getters,         // tp_getset
-  0,                                    // tp_base
-  0,                                    // tp_dict
-  0,                                    // tp_descr_get
-  0,                                    // tp_descr_set
-  0,                                    // tp_dictoffset
-  0,                                    // tp_init
-  PyType_GenericAlloc,                  // tp_alloc
-  PyType_GenericNew,                    // tp_new
-  PyObject_Del,                         // tp_free
+  message_descriptor::Getters,          // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
 };
 
-
-namespace cfield_descriptor {
-
-static void Dealloc(CFieldDescriptor* self) {
-  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+PyObject* PyMessageDescriptor_New(
+    const Descriptor* message_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyMessageDescriptor_Type, message_descriptor);
 }
 
-static PyObject* GetFullName(CFieldDescriptor* self, void *closure) {
-  return PyString_FromStringAndSize(
-      self->descriptor->full_name().c_str(),
-      self->descriptor->full_name().size());
+const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<const Descriptor*>(
+      reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
 }
 
-static PyObject* GetName(CFieldDescriptor *self, void *closure) {
-  return PyString_FromStringAndSize(
-      self->descriptor->name().c_str(),
-      self->descriptor->name().size());
+namespace field_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const FieldDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const FieldDescriptor*>(self->descriptor);
 }
 
-static PyObject* GetCppType(CFieldDescriptor *self, void *closure) {
-  return PyInt_FromLong(self->descriptor->cpp_type());
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
 }
 
-static PyObject* GetLabel(CFieldDescriptor *self, void *closure) {
-  return PyInt_FromLong(self->descriptor->label());
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
 }
 
-static PyObject* GetID(CFieldDescriptor *self, void *closure) {
+static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->type());
+}
+
+static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->cpp_type());
+}
+
+static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->label());
+}
+
+static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->number());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->index());
+}
+
+static PyObject* GetID(PyBaseDescriptor *self, void *closure) {
   return PyLong_FromVoidPtr(self);
 }
 
+static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) {
+  return PyBool_FromLong(_GetDescriptor(self)->is_extension());
+}
+
+static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) {
+  return PyBool_FromLong(_GetDescriptor(self)->has_default_value());
+}
+
+static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
+  PyObject *result;
+
+  switch (_GetDescriptor(self)->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      int32 value = _GetDescriptor(self)->default_value_int32();
+      result = PyInt_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      int64 value = _GetDescriptor(self)->default_value_int64();
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      uint32 value = _GetDescriptor(self)->default_value_uint32();
+      result = PyInt_FromSize_t(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      uint64 value = _GetDescriptor(self)->default_value_uint64();
+      result = PyLong_FromUnsignedLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = _GetDescriptor(self)->default_value_float();
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = _GetDescriptor(self)->default_value_double();
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      bool value = _GetDescriptor(self)->default_value_bool();
+      result = PyBool_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string value = _GetDescriptor(self)->default_value_string();
+      result = ToStringObject(_GetDescriptor(self), value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      const EnumValueDescriptor* value =
+          _GetDescriptor(self)->default_value_enum();
+      result = PyInt_FromLong(value->number());
+      break;
+    }
+    default:
+      PyErr_Format(PyExc_NotImplementedError, "default value for %s",
+                   _GetDescriptor(self)->full_name().c_str());
+      return NULL;
+  }
+  return result;
+}
+
+static PyObject* GetCDescriptor(PyObject *self, void *closure) {
+  Py_INCREF(self);
+  return self;
+}
+
+static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) {
+  const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type();
+  if (enum_type) {
+    return PyEnumDescriptor_New(enum_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) {
+  return CheckCalledFromGeneratedFile("enum_type");
+}
+
+static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* message_type = _GetDescriptor(self)->message_type();
+  if (message_type) {
+    return PyMessageDescriptor_New(message_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetMessageType(PyBaseDescriptor *self, PyObject *value,
+                          void *closure) {
+  return CheckCalledFromGeneratedFile("message_type");
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_New(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("containing_type");
+}
+
+static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* extension_scope =
+      _GetDescriptor(self)->extension_scope();
+  if (extension_scope) {
+    return PyMessageDescriptor_New(extension_scope);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) {
+  const OneofDescriptor* containing_oneof =
+      _GetDescriptor(self)->containing_oneof();
+  if (containing_oneof) {
+    return PyOneofDescriptor_New(containing_oneof);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value,
+                              void *closure) {
+  return CheckCalledFromGeneratedFile("containing_oneof");
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const FieldOptions& options(_GetDescriptor(self)->options());
+  if (&options != &FieldOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+
 static PyGetSetDef Getters[] = {
   { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
   { C("name"), (getter)GetName, NULL, "Unqualified name", NULL},
+  { C("type"), (getter)GetType, NULL, "C++ Type", NULL},
   { C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL},
   { C("label"), (getter)GetLabel, NULL, "Label", NULL},
+  { C("number"), (getter)GetNumber, NULL, "Number", NULL},
+  { C("index"), (getter)GetIndex, NULL, "Index", NULL},
+  { C("default_value"), (getter)GetDefaultValue, NULL, "Default Value", NULL},
+  { C("has_default_value"), (getter)HasDefaultValue, NULL, NULL, NULL},
+  { C("is_extension"), (getter)IsExtension, NULL, "ID", NULL},
   { C("id"), (getter)GetID, NULL, "ID", NULL},
+  { C("_cdescriptor"), (getter)GetCDescriptor, NULL, "HAACK REMOVE ME", NULL},
+
+  { C("message_type"), (getter)GetMessageType, (setter)SetMessageType, "Message type", NULL},
+  { C("enum_type"), (getter)GetEnumType, (setter)SetEnumType, "Enum type", NULL},
+  { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL},
+  { C("extension_scope"), (getter)GetExtensionScope, (setter)NULL, "Extension scope", NULL},
+  { C("containing_oneof"), (getter)GetContainingOneof, (setter)SetContainingOneof, "Containing oneof", NULL},
+  { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
+  { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
   {NULL}
 };
 
-}  // namespace cfield_descriptor
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  {NULL}
+};
 
-PyTypeObject CFieldDescriptor_Type = {
+}  // namespace field_descriptor
+
+PyTypeObject PyFieldDescriptor_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
   C("google.protobuf.internal."
-    "_net_proto2___python."
-    "CFieldDescriptor"),                // tp_name
-  sizeof(CFieldDescriptor),             // tp_basicsize
+    "_message.FieldDescriptor"),        // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
   0,                                    // tp_itemsize
-  (destructor)cfield_descriptor::Dealloc,  // tp_dealloc
+  0,                                    // tp_dealloc
   0,                                    // tp_print
   0,                                    // tp_getattr
   0,                                    // tp_setattr
@@ -208,10 +862,418 @@
   0,                                    // tp_weaklistoffset
   0,                                    // tp_iter
   0,                                    // tp_iternext
-  0,                                    // tp_methods
+  field_descriptor::Methods,            // tp_methods
   0,                                    // tp_members
-  cfield_descriptor::Getters,           // tp_getset
-  0,                                    // tp_base
+  field_descriptor::Getters,            // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyFieldDescriptor_New(
+    const FieldDescriptor* field_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyFieldDescriptor_Type, field_descriptor);
+}
+
+const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<const FieldDescriptor*>(
+      reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
+
+namespace enum_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const EnumDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const EnumDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+  return PyFileDescriptor_New(_GetDescriptor(self)->file());
+}
+
+static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) {
+  return NewEnumValuesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) {
+  return NewEnumValuesByNumber(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) {
+  return NewEnumValuesSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_New(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("containing_type");
+}
+
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const EnumOptions& options(_GetDescriptor(self)->options());
+  if (&options != &EnumOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
+  return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+  {NULL}
+};
+
+static PyGetSetDef Getters[] = {
+  { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
+  { C("name"), (getter)GetName, NULL, "last name", NULL},
+  { C("file"), (getter)GetFile, NULL, "File descriptor", NULL},
+  { C("values"), (getter)GetEnumvaluesSeq, NULL, "values", NULL},
+  { C("values_by_name"), (getter)GetEnumvaluesByName, NULL, "Enumvalues by name", NULL},
+  { C("values_by_number"), (getter)GetEnumvaluesByNumber, NULL, "Enumvalues by number", NULL},
+
+  { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL},
+  { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
+  { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+  {NULL}
+};
+
+}  // namespace enum_descriptor
+
+PyTypeObject PyEnumDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  // Keep the fully qualified _message symbol in a line for opensource.
+  C("google.protobuf.internal._message."
+    "EnumDescriptor"),                  // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  C("A Enum Descriptor"),               // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  enum_descriptor::Methods,             // tp_getset
+  0,                                    // tp_members
+  enum_descriptor::Getters,             // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyEnumDescriptor_New(
+    const EnumDescriptor* enum_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyEnumDescriptor_Type, enum_descriptor);
+}
+
+namespace enumvalue_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const EnumValueDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const EnumValueDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->number());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->index());
+}
+
+static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
+  return PyEnumDescriptor_New(_GetDescriptor(self)->type());
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const EnumValueOptions& options(_GetDescriptor(self)->options());
+  if (&options != &EnumValueOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+
+static PyGetSetDef Getters[] = {
+  { C("name"), (getter)GetName, NULL, "name", NULL},
+  { C("number"), (getter)GetNumber, NULL, "number", NULL},
+  { C("index"), (getter)GetIndex, NULL, "index", NULL},
+  { C("type"), (getter)GetType, NULL, "index", NULL},
+
+  { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
+  { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  {NULL}
+};
+
+}  // namespace enumvalue_descriptor
+
+PyTypeObject PyEnumValueDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  C("google.protobuf.internal."
+    "_message.EnumValueDescriptor"),    // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  C("A EnumValue Descriptor"),          // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  enumvalue_descriptor::Methods,        // tp_methods
+  0,                                    // tp_members
+  enumvalue_descriptor::Getters,        // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyEnumValueDescriptor_New(
+    const EnumValueDescriptor* enumvalue_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyEnumValueDescriptor_Type, enumvalue_descriptor);
+}
+
+namespace file_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) {
+  return reinterpret_cast<const FileDescriptor*>(self->base.descriptor);
+}
+
+static void Dealloc(PyFileDescriptor* self) {
+  Py_XDECREF(self->serialized_pb);
+  descriptor::Dealloc(&self->base);
+}
+
+static PyObject* GetName(PyFileDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetPackage(PyFileDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->package());
+}
+
+static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) {
+  PyObject *serialized_pb = self->serialized_pb;
+  if (serialized_pb != NULL) {
+    Py_INCREF(serialized_pb);
+    return serialized_pb;
+  }
+  FileDescriptorProto file_proto;
+  _GetDescriptor(self)->CopyTo(&file_proto);
+  string contents;
+  file_proto.SerializePartialToString(&contents);
+  self->serialized_pb = PyBytes_FromStringAndSize(
+      contents.c_str(), contents.size());
+  if (self->serialized_pb == NULL) {
+    return NULL;
+  }
+  Py_INCREF(self->serialized_pb);
+  return self->serialized_pb;
+}
+
+static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) {
+  return NewFileMessageTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) {
+  return NewFileEnumTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) {
+  return NewFileExtensionsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) {
+  return NewFileDependencies(_GetDescriptor(self));
+}
+
+static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) {
+  return NewFilePublicDependencies(_GetDescriptor(self));
+}
+
+static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) {
+  const FileOptions& options(_GetDescriptor(self)->options());
+  if (&options != &FileOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyFileDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyFileDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyFileDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
+  return PyString_InternFromString(
+      FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
+}
+
+static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
+  return CopyToPythonProto<FileDescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyGetSetDef Getters[] = {
+  { C("name"), (getter)GetName, NULL, "name", NULL},
+  { C("package"), (getter)GetPackage, NULL, "package", NULL},
+  { C("serialized_pb"), (getter)GetSerializedPb, NULL, NULL, NULL},
+  { C("message_types_by_name"), (getter)GetMessageTypesByName, NULL, "Messages by name", NULL},
+  { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enums by name", NULL},
+  { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL},
+  { C("dependencies"), (getter)GetDependencies, NULL, "Dependencies", NULL},
+  { C("public_dependencies"), (getter)GetPublicDependencies, NULL, "Dependencies", NULL},
+
+  { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
+  { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+  { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+  {NULL}
+};
+
+}  // namespace file_descriptor
+
+PyTypeObject PyFileDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  C("google.protobuf.internal."
+    "_message.FileDescriptor"),         // tp_name
+  sizeof(PyFileDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  (destructor)file_descriptor::Dealloc, // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  C("A File Descriptor"),               // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  file_descriptor::Methods,             // tp_methods
+  0,                                    // tp_members
+  file_descriptor::Getters,             // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
   0,                                    // tp_dict
   0,                                    // tp_descr_get
   0,                                    // tp_descr_set
@@ -222,283 +1284,183 @@
   PyObject_Del,                         // tp_free
 };
 
-
-namespace cdescriptor_pool {
-
-PyDescriptorPool* NewDescriptorPool() {
-  PyDescriptorPool* cdescriptor_pool = PyObject_New(
-      PyDescriptorPool, &PyDescriptorPool_Type);
-  if (cdescriptor_pool == NULL) {
-    return NULL;
-  }
-
-  // Build a DescriptorPool for messages only declared in Python libraries.
-  // generated_pool() contains all messages linked in C++ libraries, and is used
-  // as underlay.
-  cdescriptor_pool->pool = new google::protobuf::DescriptorPool(
-      google::protobuf::DescriptorPool::generated_pool());
-
-  // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
-  // storage.
-  cdescriptor_pool->classes_by_descriptor =
-      new PyDescriptorPool::ClassesByMessageMap();
-
-  return cdescriptor_pool;
+PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyFileDescriptor_Type, file_descriptor);
 }
 
-static void Dealloc(PyDescriptorPool* self) {
-  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
-  for (iterator it = self->classes_by_descriptor->begin();
-       it != self->classes_by_descriptor->end(); ++it) {
-    Py_DECREF(it->second);
+PyObject* PyFileDescriptor_NewWithPb(
+    const FileDescriptor* file_descriptor, PyObject *serialized_pb) {
+  PyObject* py_descriptor = PyFileDescriptor_New(file_descriptor);
+  if (py_descriptor == NULL) {
+    return NULL;
   }
-  delete self->classes_by_descriptor;
-  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+  if (serialized_pb != NULL) {
+    PyFileDescriptor* cfile_descriptor =
+        reinterpret_cast<PyFileDescriptor*>(py_descriptor);
+    Py_XINCREF(serialized_pb);
+    cfile_descriptor->serialized_pb = serialized_pb;
+  }
+
+  return py_descriptor;
 }
 
-const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
-                                                const string& name) {
-  return self->pool->FindMessageTypeByName(name);
+namespace oneof_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const OneofDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const OneofDescriptor*>(self->descriptor);
 }
 
-static PyObject* NewCMessageDescriptor(
-    const google::protobuf::Descriptor* message_descriptor) {
-  CMessageDescriptor* cmessage_descriptor = PyObject_New(
-      CMessageDescriptor, &CMessageDescriptor_Type);
-  if (cmessage_descriptor == NULL) {
-    return NULL;
-  }
-  cmessage_descriptor->descriptor = message_descriptor;
-
-  return reinterpret_cast<PyObject*>(cmessage_descriptor);
+static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
 }
 
-static PyObject* NewCFieldDescriptor(
-    const google::protobuf::FieldDescriptor* field_descriptor) {
-  CFieldDescriptor* cfield_descriptor = PyObject_New(
-      CFieldDescriptor, &CFieldDescriptor_Type);
-  if (cfield_descriptor == NULL) {
-    return NULL;
-  }
-  cfield_descriptor->descriptor = field_descriptor;
-
-  return reinterpret_cast<PyObject*>(cfield_descriptor);
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
 }
 
-// Add a message class to our database.
-const google::protobuf::Descriptor* RegisterMessageClass(
-    PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) {
-  ScopedPyObjectPtr full_message_name(
-      PyObject_GetAttrString(descriptor, "full_name"));
-  const char* full_name = PyString_AsString(full_message_name);
-  if (full_name == NULL) {
-    return NULL;
-  }
-  const Descriptor *message_descriptor =
-      self->pool->FindMessageTypeByName(full_name);
-  if (!message_descriptor) {
-    PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'",
-                 full_name);
-    return NULL;
-  }
-  Py_INCREF(message_class);
-  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
-  std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
-      make_pair(message_descriptor, message_class));
-  if (!ret.second) {
-    // Update case: DECREF the previous value.
-    Py_DECREF(ret.first->second);
-    ret.first->second = message_class;
-  }
-
-  // Also add the C++ descriptor to the Python descriptor class.
-  ScopedPyObjectPtr cdescriptor(NewCMessageDescriptor(message_descriptor));
-  if (cdescriptor == NULL) {
-    return NULL;
-  }
-  if (PyObject_SetAttrString(
-          descriptor, "_cdescriptor", cdescriptor) < 0) {
-      return NULL;
-  }
-  return message_descriptor;
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->index());
 }
 
-// Retrieve the message class added to our database.
-PyObject *GetMessageClass(PyDescriptorPool* self,
-                          const Descriptor *message_descriptor) {
-  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
-  iterator ret = self->classes_by_descriptor->find(message_descriptor);
-  if (ret == self->classes_by_descriptor->end()) {
-    PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
-                 message_descriptor->full_name().c_str());
-    return NULL;
+static PyObject* GetFields(PyBaseDescriptor* self, void *closure) {
+  return NewOneofFieldsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_New(containing_type);
   } else {
-    return ret->second;
+    Py_RETURN_NONE;
   }
 }
 
-PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name) {
-  const char* full_field_name = PyString_AsString(name);
-  if (full_field_name == NULL) {
-    return NULL;
-  }
+static PyGetSetDef Getters[] = {
+  { C("name"), (getter)GetName, NULL, "Name", NULL},
+  { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
+  { C("index"), (getter)GetIndex, NULL, "Index", NULL},
 
-  const google::protobuf::FieldDescriptor* field_descriptor = NULL;
-
-  field_descriptor = self->pool->FindFieldByName(full_field_name);
-
-  if (field_descriptor == NULL) {
-    PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
-                 full_field_name);
-    return NULL;
-  }
-
-  return NewCFieldDescriptor(field_descriptor);
-}
-
-PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
-  const char* full_field_name = PyString_AsString(arg);
-  if (full_field_name == NULL) {
-    return NULL;
-  }
-
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      self->pool->FindExtensionByName(full_field_name);
-  if (field_descriptor == NULL) {
-    PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
-                 full_field_name);
-    return NULL;
-  }
-
-  return NewCFieldDescriptor(field_descriptor);
-}
-
-static PyMethodDef Methods[] = {
-  { C("FindFieldByName"),
-    (PyCFunction)FindFieldByName,
-    METH_O,
-    C("Searches for a field descriptor by full name.") },
-  { C("FindExtensionByName"),
-    (PyCFunction)FindExtensionByName,
-    METH_O,
-    C("Searches for extension descriptor by full name.") },
+  { C("containing_type"), (getter)GetContainingType, NULL, "Containing type", NULL},
+  { C("fields"), (getter)GetFields, NULL, "Fields", NULL},
   {NULL}
 };
 
-}  // namespace cdescriptor_pool
+}  // namespace oneof_descriptor
 
-PyTypeObject PyDescriptorPool_Type = {
+PyTypeObject PyOneofDescriptor_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
   C("google.protobuf.internal."
-    "_net_proto2___python."
-    "CFieldDescriptor"),               // tp_name
-  sizeof(PyDescriptorPool),            // tp_basicsize
-  0,                                   // tp_itemsize
-  (destructor)cdescriptor_pool::Dealloc,  // tp_dealloc
-  0,                                   // tp_print
-  0,                                   // tp_getattr
-  0,                                   // tp_setattr
-  0,                                   // tp_compare
-  0,                                   // tp_repr
-  0,                                   // tp_as_number
-  0,                                   // tp_as_sequence
-  0,                                   // tp_as_mapping
-  0,                                   // tp_hash
-  0,                                   // tp_call
-  0,                                   // tp_str
-  0,                                   // tp_getattro
-  0,                                   // tp_setattro
-  0,                                   // tp_as_buffer
-  Py_TPFLAGS_DEFAULT,                  // tp_flags
-  C("A Descriptor Pool"),              // tp_doc
-  0,                                   // tp_traverse
-  0,                                   // tp_clear
-  0,                                   // tp_richcompare
-  0,                                   // tp_weaklistoffset
-  0,                                   // tp_iter
-  0,                                   // tp_iternext
-  cdescriptor_pool::Methods,           // tp_methods
-  0,                                   // tp_members
-  0,                                   // tp_getset
-  0,                                   // tp_base
-  0,                                   // tp_dict
-  0,                                   // tp_descr_get
-  0,                                   // tp_descr_set
-  0,                                   // tp_dictoffset
-  0,                                   // tp_init
-  0,                                   // tp_alloc
-  0,                                   // tp_new
-  PyObject_Del,                        // tp_free
+    "_message.OneofDescriptor"),        // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  C("A Oneof Descriptor"),              // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  oneof_descriptor::Getters,            // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
 };
 
-
-// Collects errors that occur during proto file building to allow them to be
-// propagated in the python exception instead of only living in ERROR logs.
-class BuildFileErrorCollector : public google::protobuf::DescriptorPool::ErrorCollector {
- public:
-  BuildFileErrorCollector() : error_message(""), had_errors(false) {}
-
-  void AddError(const string& filename, const string& element_name,
-                const Message* descriptor, ErrorLocation location,
-                const string& message) {
-    // Replicates the logging behavior that happens in the C++ implementation
-    // when an error collector is not passed in.
-    if (!had_errors) {
-      error_message +=
-          ("Invalid proto descriptor for file \"" + filename + "\":\n");
-    }
-    // As this only happens on failure and will result in the program not
-    // running at all, no effort is made to optimize this string manipulation.
-    error_message += ("  " + element_name + ": " + message + "\n");
-  }
-
-  string error_message;
-  bool had_errors;
-};
-
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
-  char* message_type;
-  Py_ssize_t message_len;
-
-  if (PyBytes_AsStringAndSize(arg, &message_type, &message_len) < 0) {
-    return NULL;
-  }
-
-  google::protobuf::FileDescriptorProto file_proto;
-  if (!file_proto.ParseFromArray(message_type, message_len)) {
-    PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
-    return NULL;
-  }
-
-  // If the file was already part of a C++ library, all its descriptors are in
-  // the underlying pool.  No need to do anything else.
-  if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
-          file_proto.name()) != NULL) {
-    Py_RETURN_NONE;
-  }
-
-  BuildFileErrorCollector error_collector;
-  const google::protobuf::FileDescriptor* descriptor =
-      GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto,
-                                                           &error_collector);
-  if (descriptor == NULL) {
-    PyErr_Format(PyExc_TypeError,
-                 "Couldn't build proto file into descriptor pool!\n%s",
-                 error_collector.error_message.c_str());
-    return NULL;
-  }
-
-  Py_RETURN_NONE;
+PyObject* PyOneofDescriptor_New(
+    const OneofDescriptor* oneof_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyOneofDescriptor_Type, oneof_descriptor);
 }
 
-bool InitDescriptor() {
-  if (PyType_Ready(&CMessageDescriptor_Type) < 0)
+// Add a enum values to a type dictionary.
+static bool AddEnumValues(PyTypeObject *type,
+                          const EnumDescriptor* enum_descriptor) {
+  for (int i = 0; i < enum_descriptor->value_count(); ++i) {
+    const EnumValueDescriptor* value = enum_descriptor->value(i);
+    ScopedPyObjectPtr obj(PyInt_FromLong(value->number()));
+    if (obj == NULL) {
+      return false;
+    }
+    if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj) < 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static bool AddIntConstant(PyTypeObject *type, const char* name, int value) {
+  ScopedPyObjectPtr obj(PyInt_FromLong(value));
+  if (PyDict_SetItemString(type->tp_dict, name, obj) < 0) {
     return false;
-  if (PyType_Ready(&CFieldDescriptor_Type) < 0)
+  }
+  return true;
+}
+
+
+bool InitDescriptor() {
+  if (PyType_Ready(&PyMessageDescriptor_Type) < 0)
     return false;
 
-  PyDescriptorPool_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyDescriptorPool_Type) < 0)
+  if (PyType_Ready(&PyFieldDescriptor_Type) < 0)
+    return false;
+
+  if (!AddEnumValues(&PyFieldDescriptor_Type,
+                     FieldDescriptorProto::Label_descriptor())) {
+    return false;
+  }
+  if (!AddEnumValues(&PyFieldDescriptor_Type,
+                     FieldDescriptorProto::Type_descriptor())) {
+    return false;
+  }
+#define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \
+    &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME)
+  if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) {
+    return false;
+  }
+#undef ADD_FIELDDESC_CONSTANT
+
+  if (PyType_Ready(&PyEnumDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyFileDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyOneofDescriptor_Type) < 0)
+    return false;
+
+  if (!InitDescriptorMappingTypes())
     return false;
 
   return true;
diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h
index 9e5957b..ba6e729 100644
--- a/python/google/protobuf/pyext/descriptor.h
+++ b/python/google/protobuf/pyext/descriptor.h
@@ -34,105 +34,55 @@
 #define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__
 
 #include <Python.h>
-#include <structmember.h>
-
-#include <google/protobuf/stubs/hash.h>
 
 #include <google/protobuf/descriptor.h>
 
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-typedef int Py_ssize_t;
-#define PY_SSIZE_T_MAX INT_MAX
-#define PY_SSIZE_T_MIN INT_MIN
-#endif
-
 namespace google {
 namespace protobuf {
 namespace python {
 
-typedef struct CMessageDescriptor {
-  PyObject_HEAD
+extern PyTypeObject PyMessageDescriptor_Type;
+extern PyTypeObject PyFieldDescriptor_Type;
+extern PyTypeObject PyEnumDescriptor_Type;
+extern PyTypeObject PyEnumValueDescriptor_Type;
+extern PyTypeObject PyFileDescriptor_Type;
+extern PyTypeObject PyOneofDescriptor_Type;
 
-  // The proto2 descriptor that this object represents.
-  const google::protobuf::Descriptor* descriptor;
-} CMessageDescriptor;
+// Return a new reference to a Descriptor object.
+// The C++ pointer is usually borrowed from the global DescriptorPool.
+// In any case, it must stay alive as long as the Python object.
+PyObject* PyMessageDescriptor_New(const Descriptor* descriptor);
+PyObject* PyFieldDescriptor_New(const FieldDescriptor* descriptor);
+PyObject* PyEnumDescriptor_New(const EnumDescriptor* descriptor);
+PyObject* PyEnumValueDescriptor_New(const EnumValueDescriptor* descriptor);
+PyObject* PyOneofDescriptor_New(const OneofDescriptor* descriptor);
+PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor);
 
+// Alternate constructor of PyFileDescriptor, used when we already have a
+// serialized FileDescriptorProto that can be cached.
+// Returns a new reference.
+PyObject* PyFileDescriptor_NewWithPb(const FileDescriptor* file_descriptor,
+                                     PyObject* serialized_pb);
 
-typedef struct CFieldDescriptor {
-  PyObject_HEAD
-
-  // The proto2 descriptor that this object represents.
-  const google::protobuf::FieldDescriptor* descriptor;
-} CFieldDescriptor;
-
-
-// Wraps operations to the global DescriptorPool which contains information
-// about all messages and fields.
-//
-// There is normally one pool per process. We make it a Python object only
-// because it contains many Python references.
-// TODO(amauryfa): See whether such objects can appear in reference cycles, and
-// consider adding support for the cyclic GC.
-//
-// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool
-// namespace.
-typedef struct PyDescriptorPool {
-  PyObject_HEAD
-
-  google::protobuf::DescriptorPool* pool;
-
-  // Make our own mapping to retrieve Python classes from C++ descriptors.
-  //
-  // Descriptor pointers stored here are owned by the DescriptorPool above.
-  // Python references to classes are owned by this PyDescriptorPool.
-  typedef hash_map<const Descriptor *, PyObject *> ClassesByMessageMap;
-  ClassesByMessageMap *classes_by_descriptor;
-} PyDescriptorPool;
-
-
-extern PyTypeObject CMessageDescriptor_Type;
-extern PyTypeObject CFieldDescriptor_Type;
-
-extern PyTypeObject PyDescriptorPool_Type;
-
-
-namespace cdescriptor_pool {
-
-// Builds a new DescriptorPool. Normally called only once per process.
-PyDescriptorPool* NewDescriptorPool();
-
-// Looks up a message by name.
-// Returns a message Descriptor, or NULL if not found.
-const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
-                                                const string& name);
-
-// Registers a new Python class for the given message descriptor.
-// Returns the message Descriptor.
-// On error, returns NULL with a Python exception set.
-const google::protobuf::Descriptor* RegisterMessageClass(
-    PyDescriptorPool* self, PyObject *message_class, PyObject *descriptor);
-
-// Retrieves the Python class registered with the given message descriptor.
-//
-// Returns a *borrowed* reference if found, otherwise returns NULL with an
+// Return the C++ descriptor pointer.
+// This function checks the parameter type; on error, return NULL with a Python
 // exception set.
-PyObject *GetMessageClass(PyDescriptorPool* self,
-                          const Descriptor *message_descriptor);
+const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj);
+const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj);
 
-// Looks up a field by name. Returns a CDescriptor corresponding to
-// the field on success, or NULL on failure.
+// Returns the raw C++ pointer.
+const void* PyDescriptor_AsVoidPtr(PyObject* obj);
+
+// Check that the calling Python code is the global scope of a _pb2.py module.
+// This function is used to support the current code generated by the proto
+// compiler, which insists on modifying descriptors after they have been
+// created.
 //
-// Returns a new reference.
-PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name);
-
-// Looks up an extension by name. Returns a CDescriptor corresponding
-// to the field on success, or NULL on failure.
+// stacklevel indicates which Python frame should be the _pb2.py module.
 //
-// Returns a new reference.
-PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg);
-}  // namespace cdescriptor_pool
+// Don't use this function outside descriptor classes.
+bool _CalledFromGeneratedFile(int stacklevel);
 
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* args);
 bool InitDescriptor();
 
 }  // namespace python
diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc
new file mode 100644
index 0000000..06edebf
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_containers.cc
@@ -0,0 +1,1564 @@
+// 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.
+
+// Mappings and Sequences of descriptors.
+// Used by Descriptor.fields_by_name, EnumDescriptor.values...
+//
+// They avoid the allocation of a full dictionary or a full list: they simply
+// store a pointer to the parent descriptor, use the C++ Descriptor methods (see
+// google/protobuf/descriptor.h) to retrieve other descriptors, and create
+// Python objects on the fly.
+//
+// The containers fully conform to abc.Mapping and abc.Sequence, and behave just
+// like read-only dictionaries and lists.
+//
+// Because the interface of C++ Descriptors is quite regular, this file actually
+// defines only three types, the exact behavior of a container is controlled by
+// a DescriptorContainerDef structure, which contains functions that uses the
+// public Descriptor API.
+//
+// Note: This DescriptorContainerDef is similar to the "virtual methods table"
+// that a C++ compiler generates for a class. We have to make it explicit
+// because the Python API is based on C, and does not play well with C++
+// inheritance.
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/pyext/descriptor_containers.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #define PyString_FromFormat PyUnicode_FromFormat
+  #define PyInt_FromLong PyLong_FromLong
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #endif
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+struct PyContainer;
+
+typedef int (*CountMethod)(PyContainer* self);
+typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
+typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
+typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
+typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
+typedef const string& (*GetItemNameMethod)(const void* descriptor);
+typedef int (*GetItemNumberMethod)(const void* descriptor);
+typedef int (*GetItemIndexMethod)(const void* descriptor);
+
+struct DescriptorContainerDef {
+  const char* mapping_name;
+  // Returns the number of items in the container.
+  CountMethod count_fn;
+  // Retrieve item by index (usually the order of declaration in the proto file)
+  // Used by sequences, but also iterators. 0 <= index < Count().
+  GetByIndexMethod get_by_index_fn;
+  // Retrieve item by name (usually a call to some 'FindByName' method).
+  // Used by "by_name" mappings.
+  GetByNameMethod get_by_name_fn;
+  // Retrieve item by declared number (field tag, or enum value).
+  // Used by "by_number" mappings.
+  GetByNumberMethod get_by_number_fn;
+  // Converts a item C++ descriptor to a Python object. Returns a new reference.
+  NewObjectFromItemMethod new_object_from_item_fn;
+  // Retrieve the name of an item. Used by iterators on "by_name" mappings.
+  GetItemNameMethod get_item_name_fn;
+  // Retrieve the number of an item. Used by iterators on "by_number" mappings.
+  GetItemNumberMethod get_item_number_fn;
+  // Retrieve the index of an item for the container type.
+  // Used by "__contains__".
+  // If not set, "x in sequence" will do a linear search.
+  GetItemIndexMethod get_item_index_fn;
+};
+
+struct PyContainer {
+  PyObject_HEAD
+
+  // The proto2 descriptor this container belongs to the global DescriptorPool.
+  const void* descriptor;
+
+  // A pointer to a static structure with function pointers that control the
+  // behavior of the container. Very similar to the table of virtual functions
+  // of a C++ class.
+  const DescriptorContainerDef* container_def;
+
+  // The kind of container: list, or dict by name or value.
+  enum ContainerKind {
+    KIND_SEQUENCE,
+    KIND_BYNAME,
+    KIND_BYNUMBER,
+  } kind;
+};
+
+struct PyContainerIterator {
+  PyObject_HEAD
+
+  // The container we are iterating over. Own a reference.
+  PyContainer* container;
+
+  // The current index in the iterator.
+  int index;
+
+  // The kind of container: list, or dict by name or value.
+  enum IterKind {
+    KIND_ITERKEY,
+    KIND_ITERVALUE,
+    KIND_ITERITEM,
+    KIND_ITERVALUE_REVERSED,  // For sequences
+  } kind;
+};
+
+namespace descriptor {
+
+// Returns the C++ item descriptor for a given Python key.
+// When the descriptor is found, return true and set *item.
+// When the descriptor is not found, return true, but set *item to NULL.
+// On error, returns false with an exception set.
+static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
+  switch (self->kind) {
+    case PyContainer::KIND_BYNAME:
+      {
+        char* name;
+        Py_ssize_t name_size;
+        if (PyString_AsStringAndSize(key, &name, &name_size) < 0) {
+          if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+            // Not a string, cannot be in the container.
+            PyErr_Clear();
+            *item = NULL;
+            return true;
+          }
+          return false;
+        }
+        *item = self->container_def->get_by_name_fn(
+            self, string(name, name_size));
+        return true;
+      }
+    case PyContainer::KIND_BYNUMBER:
+      {
+        Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
+        if (number == -1 && PyErr_Occurred()) {
+          if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+            // Not a number, cannot be in the container.
+            PyErr_Clear();
+            *item = NULL;
+            return true;
+          }
+          return false;
+        }
+        *item = self->container_def->get_by_number_fn(self, number);
+        return true;
+      }
+    default:
+      PyErr_SetNone(PyExc_NotImplementedError);
+      return false;
+  }
+}
+
+// Returns the key of the object at the given index.
+// Used when iterating over mappings.
+static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
+  const void* item = self->container_def->get_by_index_fn(self, index);
+  switch (self->kind) {
+    case PyContainer::KIND_BYNAME:
+      {
+        const string& name(self->container_def->get_item_name_fn(item));
+        return PyString_FromStringAndSize(name.c_str(), name.size());
+      }
+    case PyContainer::KIND_BYNUMBER:
+      {
+        int value = self->container_def->get_item_number_fn(item);
+        return PyInt_FromLong(value);
+      }
+    default:
+      PyErr_SetNone(PyExc_NotImplementedError);
+      return NULL;
+  }
+}
+
+// Returns the object at the given index.
+// Also used when iterating over mappings.
+static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) {
+  return self->container_def->new_object_from_item_fn(
+      self->container_def->get_by_index_fn(self, index));
+}
+
+static Py_ssize_t Length(PyContainer* self) {
+  return self->container_def->count_fn(self);
+}
+
+// The DescriptorMapping type.
+
+static PyObject* Subscript(PyContainer* self, PyObject* key) {
+  const void* item = NULL;
+  if (!_GetItemByKey(self, key, &item)) {
+    return NULL;
+  }
+  if (!item) {
+    PyErr_SetObject(PyExc_KeyError, key);
+    return NULL;
+  }
+  return self->container_def->new_object_from_item_fn(item);
+}
+
+static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) {
+  if (_CalledFromGeneratedFile(0)) {
+    return 0;
+  }
+  PyErr_Format(PyExc_TypeError,
+               "'%.200s' object does not support item assignment",
+               Py_TYPE(self)->tp_name);
+  return -1;
+}
+
+static PyMappingMethods MappingMappingMethods = {
+  (lenfunc)Length,               // mp_length
+  (binaryfunc)Subscript,         // mp_subscript
+  (objobjargproc)AssSubscript,   // mp_ass_subscript
+};
+
+static int Contains(PyContainer* self, PyObject* key) {
+  const void* item = NULL;
+  if (!_GetItemByKey(self, key, &item)) {
+    return -1;
+  }
+  if (item) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+static PyObject* ContainerRepr(PyContainer* self) {
+  const char* kind = "";
+  switch (self->kind) {
+    case PyContainer::KIND_SEQUENCE:
+      kind = "sequence";
+      break;
+    case PyContainer::KIND_BYNAME:
+      kind = "mapping by name";
+      break;
+    case PyContainer::KIND_BYNUMBER:
+      kind = "mapping by number";
+      break;
+  }
+  return PyString_FromFormat(
+      "<%s %s>", self->container_def->mapping_name, kind);
+}
+
+extern PyTypeObject DescriptorMapping_Type;
+extern PyTypeObject DescriptorSequence_Type;
+
+// A sequence container can only be equal to another sequence container, or (for
+// backward compatibility) to a list containing the same items.
+// Returns 1 if equal, 0 if unequal, -1 on error.
+static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) {
+  // Check the identity of C++ pointers.
+  if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) {
+    PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
+    if (self->descriptor == other_container->descriptor &&
+        self->container_def == other_container->container_def &&
+        self->kind == other_container->kind) {
+      return 1;
+    } else {
+      return 0;
+    }
+  }
+
+  // If other is a list
+  if (PyList_Check(other)) {
+    // return list(self) == other
+    int size = Length(self);
+    if (size != PyList_Size(other)) {
+      return false;
+    }
+    for (int index = 0; index < size; index++) {
+      ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
+      if (value1 == NULL) {
+        return -1;
+      }
+      PyObject* value2 = PyList_GetItem(other, index);
+      if (value2 == NULL) {
+        return -1;
+      }
+      int cmp = PyObject_RichCompareBool(value1, value2, Py_EQ);
+      if (cmp != 1)  // error or not equal
+          return cmp;
+    }
+    // All items were found and equal
+    return 1;
+  }
+
+  // Any other object is different.
+  return 0;
+}
+
+// A mapping container can only be equal to another mapping container, or (for
+// backward compatibility) to a dict containing the same items.
+// Returns 1 if equal, 0 if unequal, -1 on error.
+static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) {
+  // Check the identity of C++ pointers.
+  if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) {
+    PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
+    if (self->descriptor == other_container->descriptor &&
+        self->container_def == other_container->container_def &&
+        self->kind == other_container->kind) {
+      return 1;
+    } else {
+      return 0;
+    }
+  }
+
+  // If other is a dict
+  if (PyDict_Check(other)) {
+    // equivalent to dict(self.items()) == other
+    int size = Length(self);
+    if (size != PyDict_Size(other)) {
+      return false;
+    }
+    for (int index = 0; index < size; index++) {
+      ScopedPyObjectPtr key(_NewKey_ByIndex(self, index));
+      if (key == NULL) {
+        return -1;
+      }
+      ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
+      if (value1 == NULL) {
+        return -1;
+      }
+      PyObject* value2 = PyDict_GetItem(other, key);
+      if (value2 == NULL) {
+        // Not found in the other dictionary
+        return 0;
+      }
+      int cmp = PyObject_RichCompareBool(value1, value2, Py_EQ);
+      if (cmp != 1)  // error or not equal
+          return cmp;
+    }
+    // All items were found and equal
+    return 1;
+  }
+
+  // Any other object is different.
+  return 0;
+}
+
+static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) {
+  if (opid != Py_EQ && opid != Py_NE) {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+
+  int result;
+
+  if (self->kind == PyContainer::KIND_SEQUENCE) {
+    result = DescriptorSequence_Equal(self, other);
+  } else {
+    result = DescriptorMapping_Equal(self, other);
+  }
+  if (result < 0) {
+    return NULL;
+  }
+  if (result ^ (opid == Py_NE)) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+
+static PySequenceMethods MappingSequenceMethods = {
+    0,                      // sq_length
+    0,                      // sq_concat
+    0,                      // sq_repeat
+    0,                      // sq_item
+    0,                      // sq_slice
+    0,                      // sq_ass_item
+    0,                      // sq_ass_slice
+    (objobjproc)Contains,   // sq_contains
+};
+
+static PyObject* Get(PyContainer* self, PyObject* args) {
+  PyObject* key;
+  PyObject* default_value = Py_None;
+  if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
+    return NULL;
+  }
+
+  const void* item;
+  if (!_GetItemByKey(self, key, &item)) {
+    return NULL;
+  }
+  if (item == NULL) {
+    Py_INCREF(default_value);
+    return default_value;
+  }
+  return self->container_def->new_object_from_item_fn(item);
+}
+
+static PyObject* Keys(PyContainer* self, PyObject* args) {
+  Py_ssize_t count = Length(self);
+  ScopedPyObjectPtr list(PyList_New(count));
+  if (list == NULL) {
+    return NULL;
+  }
+  for (Py_ssize_t index = 0; index < count; ++index) {
+    PyObject* key = _NewKey_ByIndex(self, index);
+    if (key == NULL) {
+      return NULL;
+    }
+    PyList_SET_ITEM(list.get(), index, key);
+  }
+  return list.release();
+}
+
+static PyObject* Values(PyContainer* self, PyObject* args) {
+  Py_ssize_t count = Length(self);
+  ScopedPyObjectPtr list(PyList_New(count));
+  if (list == NULL) {
+    return NULL;
+  }
+  for (Py_ssize_t index = 0; index < count; ++index) {
+    PyObject* value = _NewObj_ByIndex(self, index);
+    if (value == NULL) {
+      return NULL;
+    }
+    PyList_SET_ITEM(list.get(), index, value);
+  }
+  return list.release();
+}
+
+static PyObject* Items(PyContainer* self, PyObject* args) {
+  Py_ssize_t count = Length(self);
+  ScopedPyObjectPtr list(PyList_New(count));
+  if (list == NULL) {
+    return NULL;
+  }
+  for (Py_ssize_t index = 0; index < count; ++index) {
+    ScopedPyObjectPtr obj(PyTuple_New(2));
+    if (obj == NULL) {
+      return NULL;
+    }
+    PyObject* key = _NewKey_ByIndex(self, index);
+    if (key == NULL) {
+      return NULL;
+    }
+    PyTuple_SET_ITEM(obj.get(), 0, key);
+    PyObject* value = _NewObj_ByIndex(self, index);
+    if (value == NULL) {
+      return NULL;
+    }
+    PyTuple_SET_ITEM(obj.get(), 1, value);
+    PyList_SET_ITEM(list.get(), index, obj.release());
+  }
+  return list.release();
+}
+
+static PyObject* NewContainerIterator(PyContainer* mapping,
+                                      PyContainerIterator::IterKind kind);
+
+static PyObject* Iter(PyContainer* self) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
+}
+static PyObject* IterKeys(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
+}
+static PyObject* IterValues(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE);
+}
+static PyObject* IterItems(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM);
+}
+
+static PyMethodDef MappingMethods[] = {
+  { "get", (PyCFunction)Get, METH_VARARGS, },
+  { "keys", (PyCFunction)Keys, METH_NOARGS, },
+  { "values", (PyCFunction)Values, METH_NOARGS, },
+  { "items", (PyCFunction)Items, METH_NOARGS, },
+  { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, },
+  { "itervalues", (PyCFunction)IterValues, METH_NOARGS, },
+  { "iteritems", (PyCFunction)IterItems, METH_NOARGS, },
+  {NULL}
+};
+
+PyTypeObject DescriptorMapping_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "DescriptorMapping",                  // tp_name
+  sizeof(PyContainer),                  // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  (reprfunc)ContainerRepr,              // tp_repr
+  0,                                    // tp_as_number
+  &MappingSequenceMethods,              // tp_as_sequence
+  &MappingMappingMethods,               // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  0,                                    // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  (richcmpfunc)RichCompare,             // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  (getiterfunc)Iter,                    // tp_iter
+  0,                                    // tp_iternext
+  MappingMethods,                       // tp_methods
+  0,                                    // tp_members
+  0,                                    // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  0,                                    // tp_free
+};
+
+// The DescriptorSequence type.
+
+static PyObject* GetItem(PyContainer* self, Py_ssize_t index) {
+  if (index < 0) {
+    index += Length(self);
+  }
+  if (index < 0 || index >= Length(self)) {
+    PyErr_SetString(PyExc_IndexError, "index out of range");
+    return NULL;
+  }
+  return _NewObj_ByIndex(self, index);
+}
+
+// Returns the position of the item in the sequence, of -1 if not found.
+// This function never fails.
+int Find(PyContainer* self, PyObject* item) {
+  // The item can only be in one position: item.index.
+  // Check that self[item.index] == item, it's faster than a linear search.
+  //
+  // This assumes that sequences are only defined by syntax of the .proto file:
+  // a specific item belongs to only one sequence, depending on its position in
+  // the .proto file definition.
+  const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item);
+  if (descriptor_ptr == NULL) {
+    // Not a descriptor, it cannot be in the list.
+    return -1;
+  }
+  if (self->container_def->get_item_index_fn) {
+    int index = self->container_def->get_item_index_fn(descriptor_ptr);
+    if (index < 0 || index >= Length(self)) {
+      // This index is not from this collection.
+      return -1;
+    }
+    if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) {
+      // The descriptor at this index is not the same.
+      return -1;
+    }
+    // self[item.index] == item, so return the index.
+    return index;
+  } else {
+    // Fall back to linear search.
+    int length = Length(self);
+    for (int index=0; index < length; index++) {
+      if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) {
+        return index;
+      }
+    }
+    // Not found
+    return -1;
+  }
+}
+
+// Implements list.index(): the position of the item is in the sequence.
+static PyObject* Index(PyContainer* self, PyObject* item) {
+  int position = Find(self, item);
+  if (position < 0) {
+    // Not found
+    PyErr_SetNone(PyExc_ValueError);
+    return NULL;
+  } else {
+    return PyInt_FromLong(position);
+  }
+}
+// Implements "list.__contains__()": is the object in the sequence.
+static int SeqContains(PyContainer* self, PyObject* item) {
+  int position = Find(self, item);
+  if (position < 0) {
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+// Implements list.count(): number of occurrences of the item in the sequence.
+// An item can only appear once in a sequence. If it exists, return 1.
+static PyObject* Count(PyContainer* self, PyObject* item) {
+  int position = Find(self, item);
+  if (position < 0) {
+    return PyInt_FromLong(0);
+  } else {
+    return PyInt_FromLong(1);
+  }
+}
+
+static PyObject* Append(PyContainer* self, PyObject* args) {
+  if (_CalledFromGeneratedFile(0)) {
+    Py_RETURN_NONE;
+  }
+  PyErr_Format(PyExc_TypeError,
+               "'%.200s' object is not a mutable sequence",
+               Py_TYPE(self)->tp_name);
+  return NULL;
+}
+
+static PyObject* Reversed(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self,
+                              PyContainerIterator::KIND_ITERVALUE_REVERSED);
+}
+
+static PyMethodDef SeqMethods[] = {
+  { "index", (PyCFunction)Index, METH_O, },
+  { "count", (PyCFunction)Count, METH_O, },
+  { "append", (PyCFunction)Append, METH_O, },
+  { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
+  {NULL}
+};
+
+static PySequenceMethods SeqSequenceMethods = {
+    (lenfunc)Length,          // sq_length
+    0,                        // sq_concat
+    0,                        // sq_repeat
+    (ssizeargfunc)GetItem,    // sq_item
+    0,                        // sq_slice
+    0,                        // sq_ass_item
+    0,                        // sq_ass_slice
+    (objobjproc)SeqContains,  // sq_contains
+};
+
+PyTypeObject DescriptorSequence_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "DescriptorSequence",                 // tp_name
+  sizeof(PyContainer),                  // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  (reprfunc)ContainerRepr,              // tp_repr
+  0,                                    // tp_as_number
+  &SeqSequenceMethods,                  // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  0,                                    // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  (richcmpfunc)RichCompare,             // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  SeqMethods,                           // tp_methods
+  0,                                    // tp_members
+  0,                                    // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  0,                                    // tp_free
+};
+
+static PyObject* NewMappingByName(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_BYNAME;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewMappingByNumber(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  if (container_def->get_by_number_fn == NULL ||
+      container_def->get_item_number_fn == NULL) {
+    PyErr_SetNone(PyExc_NotImplementedError);
+    return NULL;
+  }
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_BYNUMBER;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewSequence(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_SEQUENCE;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+// Implement iterators over PyContainers.
+
+static void Iterator_Dealloc(PyContainerIterator* self) {
+  Py_CLEAR(self->container);
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyObject* Iterator_Next(PyContainerIterator* self) {
+  int count = self->container->container_def->count_fn(self->container);
+  if (self->index >= count) {
+    // Return NULL with no exception to indicate the end.
+    return NULL;
+  }
+  int index = self->index;
+  self->index += 1;
+  switch (self->kind) {
+    case PyContainerIterator::KIND_ITERKEY:
+      return _NewKey_ByIndex(self->container, index);
+    case PyContainerIterator::KIND_ITERVALUE:
+      return _NewObj_ByIndex(self->container, index);
+    case PyContainerIterator::KIND_ITERVALUE_REVERSED:
+      return _NewObj_ByIndex(self->container, count - index - 1);
+    case PyContainerIterator::KIND_ITERITEM:
+      {
+        PyObject* obj = PyTuple_New(2);
+        if (obj == NULL) {
+          return NULL;
+        }
+        PyObject* key = _NewKey_ByIndex(self->container, index);
+        if (key == NULL) {
+          Py_DECREF(obj);
+          return NULL;
+        }
+        PyTuple_SET_ITEM(obj, 0, key);
+        PyObject* value = _NewObj_ByIndex(self->container, index);
+        if (value == NULL) {
+          Py_DECREF(obj);
+          return NULL;
+        }
+        PyTuple_SET_ITEM(obj, 1, value);
+        return obj;
+      }
+    default:
+      PyErr_SetNone(PyExc_NotImplementedError);
+      return NULL;
+  }
+}
+
+static PyTypeObject ContainerIterator_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "DescriptorContainerIterator",        // tp_name
+  sizeof(PyContainerIterator),          // tp_basicsize
+  0,                                    // tp_itemsize
+  (destructor)Iterator_Dealloc,         // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  0,                                    // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  PyObject_SelfIter,                    // tp_iter
+  (iternextfunc)Iterator_Next,          // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  0,                                    // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  0,                                    // tp_free
+};
+
+static PyObject* NewContainerIterator(PyContainer* container,
+                                      PyContainerIterator::IterKind kind) {
+  PyContainerIterator* self = PyObject_New(PyContainerIterator,
+                                           &ContainerIterator_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  Py_INCREF(container);
+  self->container = container;
+  self->kind = kind;
+  self->index = 0;
+
+  return reinterpret_cast<PyObject*>(self);
+}
+
+}  // namespace descriptor
+
+// Now define the real collections!
+
+namespace message_descriptor {
+
+typedef const Descriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace fields {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->field_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindFieldByName(name);
+}
+
+static ItemDescriptor GetByNumber(PyContainer* self, int number) {
+  return GetDescriptor(self)->FindFieldByNumber(number);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->field(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemNumber(ItemDescriptor item) {
+  return item->number();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageFields",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)GetByNumber,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)GetItemNumber,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace fields
+
+PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&fields::ContainerDef, descriptor);
+}
+
+namespace nested_types {
+
+typedef const Descriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->nested_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindNestedTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->nested_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyMessageDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageNestedTypes",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace nested_types
+
+PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&nested_types::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor);
+}
+
+namespace enums {
+
+typedef const EnumDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->enum_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindEnumTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->enum_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageNestedEnums",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace enums
+
+PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&enums::ContainerDef, descriptor);
+}
+
+namespace enumvalues {
+
+// This is the "enum_values_by_name" mapping, which collects values from all
+// enum types in a message.
+//
+// Note that the behavior of the C++ descriptor is different: it will search and
+// return the first value that matches the name, whereas the Python
+// implementation retrieves the last one.
+
+typedef const EnumValueDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  int count = 0;
+  for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) {
+    count += GetDescriptor(self)->enum_type(i)->value_count();
+  }
+  return count;
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindEnumValueByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  // This is not optimal, but the number of enums *types* in a given message
+  // is small.  This function is only used when iterating over the mapping.
+  const EnumDescriptor* enum_type = NULL;
+  int enum_type_count = GetDescriptor(self)->enum_type_count();
+  for (int i = 0; i < enum_type_count; ++i) {
+    enum_type = GetDescriptor(self)->enum_type(i);
+    int enum_value_count = enum_type->value_count();
+    if (index < enum_value_count) {
+      // Found it!
+      break;
+    }
+    index -= enum_value_count;
+  }
+  // The next statement cannot overflow, because this function is only called by
+  // internal iterators which ensure that 0 <= index < Count().
+  return enum_type->value(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumValueDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageEnumValues",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)NULL,
+};
+
+}  // namespace enumvalues
+
+PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
+}
+
+namespace extensions {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->extension_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindExtensionByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->extension(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageExtensions",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace extensions
+
+PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&extensions::ContainerDef, descriptor);
+}
+
+namespace oneofs {
+
+typedef const OneofDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->oneof_decl_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindOneofByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->oneof_decl(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyOneofDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageOneofs",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace oneofs
+
+PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&oneofs::ContainerDef, descriptor);
+}
+
+}  // namespace message_descriptor
+
+namespace enum_descriptor {
+
+typedef const EnumDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace enumvalues {
+
+typedef const EnumValueDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->value_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->value(index);
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindValueByName(name);
+}
+
+static ItemDescriptor GetByNumber(PyContainer* self, int number) {
+  return GetDescriptor(self)->FindValueByNumber(number);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumValueDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemNumber(ItemDescriptor item) {
+  return item->number();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "EnumValues",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)GetByNumber,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)GetItemNumber,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace enumvalues
+
+PyObject* NewEnumValuesByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
+}
+
+PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor);
+}
+
+PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor);
+}
+
+}  // namespace enum_descriptor
+
+namespace oneof_descriptor {
+
+typedef const OneofDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace fields {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->field_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->field(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_New(item);
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index_in_oneof();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "OneofFields",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace fields
+
+PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&fields::ContainerDef, descriptor);
+}
+
+}  // namespace oneof_descriptor
+
+namespace file_descriptor {
+
+typedef const FileDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace messages {
+
+typedef const Descriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->message_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindMessageTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->message_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyMessageDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileMessages",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace messages
+
+PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) {
+  return descriptor::NewMappingByName(&messages::ContainerDef, descriptor);
+}
+
+namespace enums {
+
+typedef const EnumDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->enum_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindEnumTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->enum_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileEnums",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace enums
+
+PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) {
+  return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
+}
+
+namespace extensions {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->extension_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindExtensionByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->extension(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileExtensions",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace extensions
+
+PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) {
+  return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
+}
+
+namespace dependencies {
+
+typedef const FileDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->dependency_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->dependency(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFileDescriptor_New(item);
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileDependencies",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)NULL,
+};
+
+}  // namespace dependencies
+
+PyObject* NewFileDependencies(const FileDescriptor* descriptor) {
+  return descriptor::NewSequence(&dependencies::ContainerDef, descriptor);
+}
+
+namespace public_dependencies {
+
+typedef const FileDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->public_dependency_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->public_dependency(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFileDescriptor_New(item);
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FilePublicDependencies",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)NULL,
+};
+
+}  // namespace public_dependencies
+
+PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) {
+  return descriptor::NewSequence(&public_dependencies::ContainerDef,
+                                 descriptor);
+}
+
+}  // namespace file_descriptor
+
+
+// Register all implementations
+
+bool InitDescriptorMappingTypes() {
+  if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0)
+    return false;
+  if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0)
+    return false;
+  if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0)
+    return false;
+  return true;
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/python/google/protobuf/pyext/descriptor_containers.h b/python/google/protobuf/pyext/descriptor_containers.h
new file mode 100644
index 0000000..d81537d
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_containers.h
@@ -0,0 +1,95 @@
+// 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.
+
+// Mappings and Sequences of descriptors.
+// They implement containers like fields_by_name, EnumDescriptor.values...
+// See descriptor_containers.cc for more description.
+#include <Python.h>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class FileDescriptor;
+class EnumDescriptor;
+class OneofDescriptor;
+
+namespace python {
+
+// Initialize the various types and objects.
+bool InitDescriptorMappingTypes();
+
+// Each function below returns a Mapping, or a Sequence of descriptors.
+// They all return a new reference.
+
+namespace message_descriptor {
+PyObject* NewMessageFieldsByName(const Descriptor* descriptor);
+PyObject* NewMessageFieldsByNumber(const Descriptor* descriptor);
+PyObject* NewMessageFieldsSeq(const Descriptor* descriptor);
+
+PyObject* NewMessageNestedTypesSeq(const Descriptor* descriptor);
+PyObject* NewMessageNestedTypesByName(const Descriptor* descriptor);
+
+PyObject* NewMessageEnumsByName(const Descriptor* descriptor);
+PyObject* NewMessageEnumsSeq(const Descriptor* descriptor);
+PyObject* NewMessageEnumValuesByName(const Descriptor* descriptor);
+
+PyObject* NewMessageExtensionsByName(const Descriptor* descriptor);
+PyObject* NewMessageExtensionsSeq(const Descriptor* descriptor);
+
+PyObject* NewMessageOneofsByName(const Descriptor* descriptor);
+PyObject* NewMessageOneofsSeq(const Descriptor* descriptor);
+}  // namespace message_descriptor
+
+namespace enum_descriptor {
+PyObject* NewEnumValuesByName(const EnumDescriptor* descriptor);
+PyObject* NewEnumValuesByNumber(const EnumDescriptor* descriptor);
+PyObject* NewEnumValuesSeq(const EnumDescriptor* descriptor);
+}  // namespace enum_descriptor
+
+namespace oneof_descriptor {
+PyObject* NewOneofFieldsSeq(const OneofDescriptor* descriptor);
+}  // namespace oneof_descriptor
+
+namespace file_descriptor {
+PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileDependencies(const FileDescriptor* descriptor);
+PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor);
+}  // namespace file_descriptor
+
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/python/google/protobuf/pyext/descriptor_cpp2_test.py b/python/google/protobuf/pyext/descriptor_cpp2_test.py
deleted file mode 100644
index 3cf45a2..0000000
--- a/python/google/protobuf/pyext/descriptor_cpp2_test.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#! /usr/bin/python
-#
-# 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.
-
-"""Tests for google.protobuf.pyext behavior."""
-
-__author__ = 'anuraag@google.com (Anuraag Agrawal)'
-
-import os
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2'
-
-# We must set the implementation version above before the google3 imports.
-# pylint: disable=g-import-not-at-top
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-# Run all tests from the original module by putting them in our namespace.
-# pylint: disable=wildcard-import
-from google.protobuf.internal.descriptor_test import *
-
-
-class ConfirmCppApi2Test(basetest.TestCase):
-
-  def testImplementationSetting(self):
-    self.assertEqual('cpp', api_implementation.Type())
-    self.assertEqual(2, api_implementation.Version())
-
-
-if __name__ == '__main__':
-  basetest.main()
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
new file mode 100644
index 0000000..bc3077b
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -0,0 +1,370 @@
+// 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.
+
+// Implements the DescriptorPool, which collects all descriptors.
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#define C(str) const_cast<char*>(str)
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #endif
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+namespace cdescriptor_pool {
+
+PyDescriptorPool* NewDescriptorPool() {
+  PyDescriptorPool* cdescriptor_pool = PyObject_New(
+      PyDescriptorPool, &PyDescriptorPool_Type);
+  if (cdescriptor_pool == NULL) {
+    return NULL;
+  }
+
+  // Build a DescriptorPool for messages only declared in Python libraries.
+  // generated_pool() contains all messages linked in C++ libraries, and is used
+  // as underlay.
+  cdescriptor_pool->pool = new DescriptorPool(DescriptorPool::generated_pool());
+
+  // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
+  // storage.
+  cdescriptor_pool->classes_by_descriptor =
+      new PyDescriptorPool::ClassesByMessageMap();
+  cdescriptor_pool->interned_descriptors =
+      new hash_map<const void*, PyObject *>();
+  cdescriptor_pool->descriptor_options =
+      new hash_map<const void*, PyObject *>();
+
+  return cdescriptor_pool;
+}
+
+static void Dealloc(PyDescriptorPool* self) {
+  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+  for (iterator it = self->classes_by_descriptor->begin();
+       it != self->classes_by_descriptor->end(); ++it) {
+    Py_DECREF(it->second);
+  }
+  delete self->classes_by_descriptor;
+  delete self->interned_descriptors;  // its references were borrowed.
+  for (hash_map<const void*, PyObject*>::iterator it =
+           self->descriptor_options->begin();
+       it != self->descriptor_options->end(); ++it) {
+    Py_DECREF(it->second);
+  }
+  delete self->descriptor_options;
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const Descriptor* message_descriptor =
+      self->pool->FindMessageTypeByName(string(name, name_size));
+
+  if (message_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find message %.200s", name);
+    return NULL;
+  }
+
+  return PyMessageDescriptor_New(message_descriptor);
+}
+
+// Add a message class to our database.
+const Descriptor* RegisterMessageClass(
+    PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) {
+  ScopedPyObjectPtr full_message_name(
+      PyObject_GetAttrString(descriptor, "full_name"));
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(full_message_name, &name, &name_size) < 0) {
+    return NULL;
+  }
+  const Descriptor *message_descriptor =
+      self->pool->FindMessageTypeByName(string(name, name_size));
+  if (!message_descriptor) {
+    PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'",
+                 name);
+    return NULL;
+  }
+  Py_INCREF(message_class);
+  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+  std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
+      std::make_pair(message_descriptor, message_class));
+  if (!ret.second) {
+    // Update case: DECREF the previous value.
+    Py_DECREF(ret.first->second);
+    ret.first->second = message_class;
+  }
+  return message_descriptor;
+}
+
+// Retrieve the message class added to our database.
+PyObject *GetMessageClass(PyDescriptorPool* self,
+                          const Descriptor *message_descriptor) {
+  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+  iterator ret = self->classes_by_descriptor->find(message_descriptor);
+  if (ret == self->classes_by_descriptor->end()) {
+    PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
+                 message_descriptor->full_name().c_str());
+    return NULL;
+  } else {
+    return ret->second;
+  }
+}
+
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const FieldDescriptor* field_descriptor =
+      self->pool->FindFieldByName(string(name, name_size));
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
+                 name);
+    return NULL;
+  }
+
+  return PyFieldDescriptor_New(field_descriptor);
+}
+
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const FieldDescriptor* field_descriptor =
+      self->pool->FindExtensionByName(string(name, name_size));
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", name);
+    return NULL;
+  }
+
+  return PyFieldDescriptor_New(field_descriptor);
+}
+
+PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const EnumDescriptor* enum_descriptor =
+      self->pool->FindEnumTypeByName(string(name, name_size));
+  if (enum_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find enum %.200s", name);
+    return NULL;
+  }
+
+  return PyEnumDescriptor_New(enum_descriptor);
+}
+
+PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const OneofDescriptor* oneof_descriptor =
+      self->pool->FindOneofByName(string(name, name_size));
+  if (oneof_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find oneof %.200s", name);
+    return NULL;
+  }
+
+  return PyOneofDescriptor_New(oneof_descriptor);
+}
+
+static PyMethodDef Methods[] = {
+  { C("FindFieldByName"),
+    (PyCFunction)FindFieldByName,
+    METH_O,
+    C("Searches for a field descriptor by full name.") },
+  { C("FindExtensionByName"),
+    (PyCFunction)FindExtensionByName,
+    METH_O,
+    C("Searches for extension descriptor by full name.") },
+  {NULL}
+};
+
+}  // namespace cdescriptor_pool
+
+PyTypeObject PyDescriptorPool_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  C("google.protobuf.internal."
+    "_message.DescriptorPool"),        // tp_name
+  sizeof(PyDescriptorPool),            // tp_basicsize
+  0,                                   // tp_itemsize
+  (destructor)cdescriptor_pool::Dealloc,  // tp_dealloc
+  0,                                   // tp_print
+  0,                                   // tp_getattr
+  0,                                   // tp_setattr
+  0,                                   // tp_compare
+  0,                                   // tp_repr
+  0,                                   // tp_as_number
+  0,                                   // tp_as_sequence
+  0,                                   // tp_as_mapping
+  0,                                   // tp_hash
+  0,                                   // tp_call
+  0,                                   // tp_str
+  0,                                   // tp_getattro
+  0,                                   // tp_setattro
+  0,                                   // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  // tp_flags
+  C("A Descriptor Pool"),              // tp_doc
+  0,                                   // tp_traverse
+  0,                                   // tp_clear
+  0,                                   // tp_richcompare
+  0,                                   // tp_weaklistoffset
+  0,                                   // tp_iter
+  0,                                   // tp_iternext
+  cdescriptor_pool::Methods,           // tp_methods
+  0,                                   // tp_members
+  0,                                   // tp_getset
+  0,                                   // tp_base
+  0,                                   // tp_dict
+  0,                                   // tp_descr_get
+  0,                                   // tp_descr_set
+  0,                                   // tp_dictoffset
+  0,                                   // tp_init
+  0,                                   // tp_alloc
+  0,                                   // tp_new
+  PyObject_Del,                        // tp_free
+};
+
+// The code below loads new Descriptors from a serialized FileDescriptorProto.
+
+
+// Collects errors that occur during proto file building to allow them to be
+// propagated in the python exception instead of only living in ERROR logs.
+class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+  BuildFileErrorCollector() : error_message(""), had_errors(false) {}
+
+  void AddError(const string& filename, const string& element_name,
+                const Message* descriptor, ErrorLocation location,
+                const string& message) {
+    // Replicates the logging behavior that happens in the C++ implementation
+    // when an error collector is not passed in.
+    if (!had_errors) {
+      error_message +=
+          ("Invalid proto descriptor for file \"" + filename + "\":\n");
+    }
+    // As this only happens on failure and will result in the program not
+    // running at all, no effort is made to optimize this string manipulation.
+    error_message += ("  " + element_name + ": " + message + "\n");
+  }
+
+  string error_message;
+  bool had_errors;
+};
+
+PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) {
+  char* message_type;
+  Py_ssize_t message_len;
+
+  if (PyBytes_AsStringAndSize(serialized_pb, &message_type, &message_len) < 0) {
+    return NULL;
+  }
+
+  FileDescriptorProto file_proto;
+  if (!file_proto.ParseFromArray(message_type, message_len)) {
+    PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
+    return NULL;
+  }
+
+  // If the file was already part of a C++ library, all its descriptors are in
+  // the underlying pool.  No need to do anything else.
+  const FileDescriptor* generated_file =
+      DescriptorPool::generated_pool()->FindFileByName(file_proto.name());
+  if (generated_file != NULL) {
+    return PyFileDescriptor_NewWithPb(generated_file, serialized_pb);
+  }
+
+  BuildFileErrorCollector error_collector;
+  const FileDescriptor* descriptor =
+      GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto,
+                                                           &error_collector);
+  if (descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError,
+                 "Couldn't build proto file into descriptor pool!\n%s",
+                 error_collector.error_message.c_str());
+    return NULL;
+  }
+
+  return PyFileDescriptor_NewWithPb(descriptor, serialized_pb);
+}
+
+static PyDescriptorPool* global_cdescriptor_pool = NULL;
+
+bool InitDescriptorPool() {
+  if (PyType_Ready(&PyDescriptorPool_Type) < 0)
+    return false;
+
+  global_cdescriptor_pool = cdescriptor_pool::NewDescriptorPool();
+  if (global_cdescriptor_pool == NULL) {
+    return false;
+  }
+
+  return true;
+}
+
+PyDescriptorPool* GetDescriptorPool() {
+  return global_cdescriptor_pool;
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h
new file mode 100644
index 0000000..4e494b8
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_pool.h
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
+
+#include <Python.h>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// Wraps operations to the global DescriptorPool which contains information
+// about all messages and fields.
+//
+// There is normally one pool per process. We make it a Python object only
+// because it contains many Python references.
+// TODO(amauryfa): See whether such objects can appear in reference cycles, and
+// consider adding support for the cyclic GC.
+//
+// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool
+// namespace.
+typedef struct PyDescriptorPool {
+  PyObject_HEAD
+
+  DescriptorPool* pool;
+
+  // Make our own mapping to retrieve Python classes from C++ descriptors.
+  //
+  // Descriptor pointers stored here are owned by the DescriptorPool above.
+  // Python references to classes are owned by this PyDescriptorPool.
+  typedef hash_map<const Descriptor*, PyObject*> ClassesByMessageMap;
+  ClassesByMessageMap* classes_by_descriptor;
+
+  // Store interned descriptors, so that the same C++ descriptor yields the same
+  // Python object. Objects are not immortal: this map does not own the
+  // references, and items are deleted when the last reference to the object is
+  // released.
+  // This is enough to support the "is" operator on live objects.
+  // All descriptors are stored here.
+  hash_map<const void*, PyObject*>* interned_descriptors;
+
+  // Cache the options for any kind of descriptor.
+  // Descriptor pointers are owned by the DescriptorPool above.
+  // Python objects are owned by the map.
+  hash_map<const void*, PyObject*>* descriptor_options;
+} PyDescriptorPool;
+
+
+extern PyTypeObject PyDescriptorPool_Type;
+
+namespace cdescriptor_pool {
+
+// Builds a new DescriptorPool. Normally called only once per process.
+PyDescriptorPool* NewDescriptorPool();
+
+// Looks up a message by name.
+// Returns a message Descriptor, or NULL if not found.
+const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
+                                        const string& name);
+
+// Registers a new Python class for the given message descriptor.
+// Returns the message Descriptor.
+// On error, returns NULL with a Python exception set.
+const Descriptor* RegisterMessageClass(
+    PyDescriptorPool* self, PyObject* message_class, PyObject* descriptor);
+
+// Retrieves the Python class registered with the given message descriptor.
+//
+// Returns a *borrowed* reference if found, otherwise returns NULL with an
+// exception set.
+PyObject* GetMessageClass(PyDescriptorPool* self,
+                          const Descriptor* message_descriptor);
+
+// Looks up a message by name. Returns a PyMessageDescriptor corresponding to
+// the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* name);
+
+// Looks up a field by name. Returns a PyFieldDescriptor corresponding to
+// the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name);
+
+// Looks up an extension by name. Returns a PyFieldDescriptor corresponding
+// to the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg);
+
+// Looks up an enum type by name. Returns a PyEnumDescriptor corresponding
+// to the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg);
+
+// Looks up a oneof by name. Returns a COneofDescriptor corresponding
+// to the oneof on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg);
+
+}  // namespace cdescriptor_pool
+
+// Implement the Python "_BuildFile" method, it takes a serialized
+// FileDescriptorProto, and adds it to the C++ DescriptorPool.
+// It returns a new FileDescriptor object, or NULL when an exception is raised.
+PyObject* Python_BuildFile(PyObject* ignored, PyObject* args);
+
+// Retrieve the global descriptor pool owned by the _message module.
+PyDescriptorPool* GetDescriptorPool();
+
+// Initialize objects used by this module.
+bool InitDescriptorPool();
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index d83b57d..8e38fc4 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -38,6 +38,7 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/repeated_composite_container.h>
 #include <google/protobuf/pyext/repeated_scalar_container.h>
@@ -48,13 +49,11 @@
 namespace protobuf {
 namespace python {
 
-extern google::protobuf::DynamicMessageFactory* global_message_factory;
-
 namespace extension_dict {
 
 // TODO(tibell): Always use self->message for clarity, just like in
 // RepeatedCompositeContainer.
-static google::protobuf::Message* GetMessage(ExtensionDict* self) {
+static Message* GetMessage(ExtensionDict* self) {
   if (self->parent != NULL) {
     return self->parent->message;
   } else {
@@ -73,10 +72,9 @@
 // TODO(tibell): Use VisitCompositeField.
 int ReleaseExtension(ExtensionDict* self,
                      PyObject* extension,
-                     const google::protobuf::FieldDescriptor* descriptor) {
-  if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
-    if (descriptor->cpp_type() ==
-        google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+                     const FieldDescriptor* descriptor) {
+  if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       if (repeated_composite_container::Release(
               reinterpret_cast<RepeatedCompositeContainer*>(
                   extension)) < 0) {
@@ -89,8 +87,7 @@
         return -1;
       }
     }
-  } else if (descriptor->cpp_type() ==
-             google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+  } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     if (cmessage::ReleaseSubMessage(
             GetMessage(self), descriptor,
             reinterpret_cast<CMessage*>(extension)) < 0) {
@@ -102,8 +99,7 @@
 }
 
 PyObject* subscript(ExtensionDict* self, PyObject* key) {
-  const google::protobuf::FieldDescriptor* descriptor =
-      cmessage::GetExtensionDescriptor(key);
+  const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
   if (descriptor == NULL) {
     return NULL;
   }
@@ -162,8 +158,7 @@
 }
 
 int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
-  const google::protobuf::FieldDescriptor* descriptor =
-      cmessage::GetExtensionDescriptor(key);
+  const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
   if (descriptor == NULL) {
     return -1;
   }
@@ -187,7 +182,7 @@
 }
 
 PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
-  const google::protobuf::FieldDescriptor* descriptor =
+  const FieldDescriptor* descriptor =
       cmessage::GetExtensionDescriptor(extension);
   if (descriptor == NULL) {
     return NULL;
@@ -208,7 +203,7 @@
 }
 
 PyObject* HasExtension(ExtensionDict* self, PyObject* extension) {
-  const google::protobuf::FieldDescriptor* descriptor =
+  const FieldDescriptor* descriptor =
       cmessage::GetExtensionDescriptor(extension);
   if (descriptor == NULL) {
     return NULL;
diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h
index 47625e2..7e1049f 100644
--- a/python/google/protobuf/pyext/extension_dict.h
+++ b/python/google/protobuf/pyext/extension_dict.h
@@ -41,7 +41,6 @@
 #include <google/protobuf/stubs/shared_ptr.h>
 #endif
 
-
 namespace google {
 namespace protobuf {
 
@@ -94,7 +93,7 @@
 // Returns 0 on success, -1 on failure.
 int ReleaseExtension(ExtensionDict* self,
                      PyObject* extension,
-                     const google::protobuf::FieldDescriptor* descriptor);
+                     const FieldDescriptor* descriptor);
 
 // Gets an extension from the dict for the given extension descriptor.
 //
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index cd956e0..a2b357b 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -39,6 +39,7 @@
 #endif
 #include <string>
 #include <vector>
+#include <structmember.h>  // A Python header file.
 
 #ifndef PyVarObject_HEAD_INIT
 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@@ -54,10 +55,12 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/extension_dict.h>
 #include <google/protobuf/pyext/repeated_composite_container.h>
 #include <google/protobuf/pyext/repeated_scalar_container.h>
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include <google/protobuf/stubs/strutil.h>
 
 #if PY_MAJOR_VERSION >= 3
   #define PyInt_Check PyLong_Check
@@ -72,6 +75,10 @@
   #else
   #define PyString_AsString(ob) \
     (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
   #endif
 #endif
 
@@ -81,14 +88,14 @@
 
 // Forward declarations
 namespace cmessage {
-static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
+static const FieldDescriptor* GetFieldDescriptor(
     CMessage* self, PyObject* name);
-static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls);
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls);
 static string GetMessageName(CMessage* self);
 int InternalReleaseFieldByDescriptor(
-    const google::protobuf::FieldDescriptor* field_descriptor,
+    const FieldDescriptor* field_descriptor,
     PyObject* composite_field,
-    google::protobuf::Message* parent_message);
+    Message* parent_message);
 }  // namespace cmessage
 
 // ---------------------------------------------------------------------
@@ -107,7 +114,7 @@
 
   // Returns 0 on success, -1 on failure.
   int VisitCMessage(CMessage* cmessage,
-                    const google::protobuf::FieldDescriptor* field_descriptor) {
+                    const FieldDescriptor* field_descriptor) {
     return 0;
   }
 };
@@ -118,8 +125,8 @@
 static int VisitCompositeField(const FieldDescriptor* descriptor,
                                PyObject* child,
                                Visitor visitor) {
-  if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
-    if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+  if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       RepeatedCompositeContainer* container =
         reinterpret_cast<RepeatedCompositeContainer*>(child);
       if (visitor.VisitRepeatedCompositeContainer(container) == -1)
@@ -130,8 +137,7 @@
       if (visitor.VisitRepeatedScalarContainer(container) == -1)
         return -1;
     }
-  } else if (descriptor->cpp_type() ==
-             google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+  } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     CMessage* cmsg = reinterpret_cast<CMessage*>(child);
     if (visitor.VisitCMessage(cmsg, descriptor) == -1)
       return -1;
@@ -149,25 +155,31 @@
   PyObject* key;
   PyObject* field;
 
-  // Never use self->message in this function, it may be already freed.
-  const google::protobuf::Descriptor* message_descriptor =
-      cmessage::GetMessageDescriptor(Py_TYPE(self));
-
   // Visit normal fields.
-  while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
-    const google::protobuf::FieldDescriptor* descriptor =
-      message_descriptor->FindFieldByName(PyString_AsString(key));
-    if (descriptor != NULL) {
-      if (VisitCompositeField(descriptor, field, visitor) == -1)
+  if (self->composite_fields) {
+    // Never use self->message in this function, it may be already freed.
+    const Descriptor* message_descriptor =
+        cmessage::GetMessageDescriptor(Py_TYPE(self));
+    while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
+      Py_ssize_t key_str_size;
+      char *key_str_data;
+      if (PyString_AsStringAndSize(key, &key_str_data, &key_str_size) != 0)
         return -1;
+      const string key_str(key_str_data, key_str_size);
+      const FieldDescriptor* descriptor =
+        message_descriptor->FindFieldByName(key_str);
+      if (descriptor != NULL) {
+        if (VisitCompositeField(descriptor, field, visitor) == -1)
+          return -1;
+      }
     }
   }
 
   // Visit extension fields.
   if (self->extensions != NULL) {
+    pos = 0;
     while (PyDict_Next(self->extensions->values, &pos, &key, &field)) {
-      const google::protobuf::FieldDescriptor* descriptor =
-          cmessage::GetExtensionDescriptor(key);
+      const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
       if (descriptor == NULL)
         return -1;
       if (VisitCompositeField(descriptor, field, visitor) == -1)
@@ -180,6 +192,8 @@
 
 // ---------------------------------------------------------------------
 
+static DynamicMessageFactory* message_factory;
+
 // Constants used for integer type range checking.
 PyObject* kPythonZero;
 PyObject* kint32min_py;
@@ -198,17 +212,8 @@
 static PyObject* kDESCRIPTOR;
 static PyObject* k_cdescriptor;
 static PyObject* kfull_name;
-static PyObject* kname;
-static PyObject* kextensions_by_name;
 static PyObject* k_extensions_by_name;
 static PyObject* k_extensions_by_number;
-static PyObject* kfields_by_name;
-
-static PyDescriptorPool* descriptor_pool;
-
-PyDescriptorPool* GetDescriptorPool() {
-  return descriptor_pool;
-}
 
 /* Is 64bit */
 void FormatTypeError(PyObject* arg, char* expected_types) {
@@ -305,14 +310,14 @@
 }
 
 bool CheckAndSetString(
-    PyObject* arg, google::protobuf::Message* message,
-    const google::protobuf::FieldDescriptor* descriptor,
-    const google::protobuf::Reflection* reflection,
+    PyObject* arg, Message* message,
+    const FieldDescriptor* descriptor,
+    const Reflection* reflection,
     bool append,
     int index) {
-  GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
-         descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES);
-  if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+  GOOGLE_DCHECK(descriptor->type() == FieldDescriptor::TYPE_STRING ||
+         descriptor->type() == FieldDescriptor::TYPE_BYTES);
+  if (descriptor->type() == FieldDescriptor::TYPE_STRING) {
     if (!PyBytes_Check(arg) && !PyUnicode_Check(arg)) {
       FormatTypeError(arg, "bytes, unicode");
       return false;
@@ -339,7 +344,7 @@
   }
 
   PyObject* encoded_string = NULL;
-  if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+  if (descriptor->type() == FieldDescriptor::TYPE_STRING) {
     if (PyBytes_Check(arg)) {
       // The bytes were already validated as correctly encoded UTF-8 above.
       encoded_string = arg;  // Already encoded.
@@ -376,9 +381,8 @@
   return true;
 }
 
-PyObject* ToStringObject(
-    const google::protobuf::FieldDescriptor* descriptor, string value) {
-  if (descriptor->type() != google::protobuf::FieldDescriptor::TYPE_STRING) {
+PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) {
+  if (descriptor->type() != FieldDescriptor::TYPE_STRING) {
     return PyBytes_FromStringAndSize(value.c_str(), value.length());
   }
 
@@ -394,8 +398,8 @@
   return result;
 }
 
-bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor,
-                                const google::protobuf::Message* message) {
+bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
+                                const Message* message) {
   if (message->GetDescriptor() == field_descriptor->containing_type()) {
     return true;
   }
@@ -405,16 +409,18 @@
   return false;
 }
 
-google::protobuf::DynamicMessageFactory* global_message_factory;
-
 namespace cmessage {
 
+DynamicMessageFactory* GetMessageFactory() {
+  return message_factory;
+}
+
 static int MaybeReleaseOverlappingOneofField(
     CMessage* cmessage,
-    const google::protobuf::FieldDescriptor* field) {
+    const FieldDescriptor* field) {
 #ifdef GOOGLE_PROTOBUF_HAS_ONEOF
-  google::protobuf::Message* message = cmessage->message;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  Message* message = cmessage->message;
+  const Reflection* reflection = message->GetReflection();
   if (!field->containing_oneof() ||
       !reflection->HasOneof(*message, field->containing_oneof()) ||
       reflection->HasField(*message, field)) {
@@ -425,13 +431,13 @@
   const OneofDescriptor* oneof = field->containing_oneof();
   const FieldDescriptor* existing_field =
       reflection->GetOneofFieldDescriptor(*message, oneof);
-  if (existing_field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+  if (existing_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
     // Non-message fields don't need to be released.
     return 0;
   }
   const char* field_name = existing_field->name().c_str();
-  PyObject* child_message = PyDict_GetItemString(
-      cmessage->composite_fields, field_name);
+  PyObject* child_message = cmessage->composite_fields ?
+      PyDict_GetItemString(cmessage->composite_fields, field_name) : NULL;
   if (child_message == NULL) {
     // No python reference to this field so no need to release.
     return 0;
@@ -450,21 +456,21 @@
 // ---------------------------------------------------------------------
 // Making a message writable
 
-static google::protobuf::Message* GetMutableMessage(
+static Message* GetMutableMessage(
     CMessage* parent,
-    const google::protobuf::FieldDescriptor* parent_field) {
-  google::protobuf::Message* parent_message = parent->message;
-  const google::protobuf::Reflection* reflection = parent_message->GetReflection();
+    const FieldDescriptor* parent_field) {
+  Message* parent_message = parent->message;
+  const Reflection* reflection = parent_message->GetReflection();
   if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) {
     return NULL;
   }
   return reflection->MutableMessage(
-      parent_message, parent_field, global_message_factory);
+      parent_message, parent_field, message_factory);
 }
 
 struct FixupMessageReference : public ChildVisitor {
   // message must outlive this object.
-  explicit FixupMessageReference(google::protobuf::Message* message) :
+  explicit FixupMessageReference(Message* message) :
       message_(message) {}
 
   int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
@@ -478,7 +484,7 @@
   }
 
  private:
-  google::protobuf::Message* message_;
+  Message* message_;
 };
 
 int AssureWritable(CMessage* self) {
@@ -490,7 +496,7 @@
     // If parent is NULL but we are trying to modify a read-only message, this
     // is a reference to a constant default instance that needs to be replaced
     // with a mutable top-level message.
-    const Message* prototype = global_message_factory->GetPrototype(
+    const Message* prototype = message_factory->GetPrototype(
         self->message->GetDescriptor());
     self->message = prototype->New();
     self->owner.reset(self->message);
@@ -500,8 +506,8 @@
       return -1;
 
     // Make self->message writable.
-    google::protobuf::Message* parent_message = self->parent->message;
-    google::protobuf::Message* mutable_message = GetMutableMessage(
+    Message* parent_message = self->parent->message;
+    Message* mutable_message = GetMutableMessage(
         self->parent,
         self->parent_field_descriptor);
     if (mutable_message == NULL) {
@@ -528,38 +534,35 @@
 
 // Retrieve the C++ Descriptor of a message class.
 // On error, returns NULL with an exception set.
-static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
   ScopedPyObjectPtr descriptor(PyObject_GetAttr(
       reinterpret_cast<PyObject*>(cls), kDESCRIPTOR));
   if (descriptor == NULL) {
     PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
     return NULL;
   }
-  ScopedPyObjectPtr cdescriptor(PyObject_GetAttr(descriptor, k_cdescriptor));
-  if (cdescriptor == NULL) {
-    PyErr_SetString(PyExc_TypeError, "Unregistered message.");
+  if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
+    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+                 descriptor->ob_type->tp_name);
     return NULL;
   }
-  if (!PyObject_TypeCheck(cdescriptor, &CMessageDescriptor_Type)) {
-    PyErr_SetString(PyExc_TypeError, "Not a CMessageDescriptor");
-    return NULL;
-  }
-  return reinterpret_cast<CMessageDescriptor*>(cdescriptor.get())->descriptor;
+  return PyMessageDescriptor_AsDescriptor(descriptor);
 }
 
 // Retrieve a C++ FieldDescriptor for a message attribute.
 // The C++ message must be valid.
 // TODO(amauryfa): This function should stay internal, because exception
 // handling is not consistent.
-static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
+static const FieldDescriptor* GetFieldDescriptor(
     CMessage* self, PyObject* name) {
-  const google::protobuf::Descriptor *message_descriptor = self->message->GetDescriptor();
-  const char* field_name = PyString_AsString(name);
-  if (field_name == NULL) {
+  const Descriptor *message_descriptor = self->message->GetDescriptor();
+  char* field_name;
+  Py_ssize_t size;
+  if (PyString_AsStringAndSize(name, &field_name, &size) < 0) {
     return NULL;
   }
-  const google::protobuf::FieldDescriptor *field_descriptor =
-      message_descriptor->FindFieldByName(field_name);
+  const FieldDescriptor *field_descriptor =
+      message_descriptor->FindFieldByName(string(field_name, size));
   if (field_descriptor == NULL) {
     // Note: No exception is set!
     return NULL;
@@ -568,19 +571,16 @@
 }
 
 // Retrieve a C++ FieldDescriptor for an extension handle.
-const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
-  ScopedPyObjectPtr cdescriptor(
-      PyObject_GetAttrString(extension, "_cdescriptor"));
-  if (cdescriptor == NULL) {
-    PyErr_SetString(PyExc_KeyError, "Unregistered extension.");
+const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
+  ScopedPyObjectPtr cdescriptor;
+  if (!PyObject_TypeCheck(extension, &PyFieldDescriptor_Type)) {
+    // Most callers consider extensions as a plain dictionary.  We should
+    // allow input which is not a field descriptor, and simply pretend it does
+    // not exist.
+    PyErr_SetObject(PyExc_KeyError, extension);
     return NULL;
   }
-  if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) {
-    PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor");
-    Py_DECREF(cdescriptor);
-    return NULL;
-  }
-  return reinterpret_cast<CFieldDescriptor*>(cdescriptor.get())->descriptor;
+  return PyFieldDescriptor_AsDescriptor(extension);
 }
 
 // If cmessage_list is not NULL, this function releases values into the
@@ -588,12 +588,12 @@
 // needs to do this to make sure CMessages stay alive if they're still
 // referenced after deletion. Repeated scalar container doesn't need to worry.
 int InternalDeleteRepeatedField(
-    google::protobuf::Message* message,
-    const google::protobuf::FieldDescriptor* field_descriptor,
+    Message* message,
+    const FieldDescriptor* field_descriptor,
     PyObject* slice,
     PyObject* cmessage_list) {
   Py_ssize_t length, from, to, step, slice_length;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  const Reflection* reflection = message->GetReflection();
   int min, max;
   length = reflection->FieldSize(*message, field_descriptor);
 
@@ -690,18 +690,18 @@
       PyErr_SetString(PyExc_ValueError, "Field name must be a string");
       return -1;
     }
-    const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
+    const FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
     if (descriptor == NULL) {
       PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.",
                    PyString_AsString(name));
       return -1;
     }
-    if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
+    if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
       ScopedPyObjectPtr container(GetAttr(self, name));
       if (container == NULL) {
         return -1;
       }
-      if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
         if (repeated_composite_container::Extend(
                 reinterpret_cast<RepeatedCompositeContainer*>(container.get()),
                 value)
@@ -716,8 +716,7 @@
           return -1;
         }
       }
-    } else if (descriptor->cpp_type() ==
-               google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+    } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       ScopedPyObjectPtr message(GetAttr(self, name));
       if (message == NULL) {
         return -1;
@@ -737,8 +736,7 @@
 
 // Allocates an incomplete Python Message: the caller must fill self->message,
 // self->owner and eventually self->parent.
-CMessage* NewEmptyMessage(PyObject* type,
-                          const google::protobuf::Descriptor *descriptor) {
+CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) {
   CMessage* self = reinterpret_cast<CMessage*>(
       PyType_GenericAlloc(reinterpret_cast<PyTypeObject*>(type), 0));
   if (self == NULL) {
@@ -751,10 +749,7 @@
   self->read_only = false;
   self->extensions = NULL;
 
-  self->composite_fields = PyDict_New();
-  if (self->composite_fields == NULL) {
-    return NULL;
-  }
+  self->composite_fields = NULL;
 
   // If there are extension_ranges, the message is "extendable". Allocate a
   // dictionary to store the extension fields.
@@ -776,12 +771,12 @@
 static PyObject* New(PyTypeObject* type,
                      PyObject* unused_args, PyObject* unused_kwargs) {
   // Retrieve the message descriptor and the default instance (=prototype).
-  const google::protobuf::Descriptor* message_descriptor = GetMessageDescriptor(type);
+  const Descriptor* message_descriptor = GetMessageDescriptor(type);
   if (message_descriptor == NULL) {
     return NULL;
   }
-  const google::protobuf::Message* default_message =
-      global_message_factory->GetPrototype(message_descriptor);
+  const Message* default_message =
+      message_factory->GetPrototype(message_descriptor);
   if (default_message == NULL) {
     PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
     return NULL;
@@ -836,7 +831,7 @@
   }
 
   int VisitCMessage(CMessage* cmessage,
-                    const google::protobuf::FieldDescriptor* field_descriptor) {
+                    const FieldDescriptor* field_descriptor) {
     cmessage->parent = NULL;
     return 0;
   }
@@ -886,12 +881,12 @@
 }
 
 PyObject* HasFieldByDescriptor(
-    CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) {
-  google::protobuf::Message* message = self->message;
+    CMessage* self, const FieldDescriptor* field_descriptor) {
+  Message* message = self->message;
   if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
     return NULL;
   }
-  if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
+  if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
     PyErr_SetString(PyExc_KeyError,
                     "Field is repeated. A singular method is required.");
     return NULL;
@@ -901,42 +896,78 @@
   return PyBool_FromLong(has_field ? 1 : 0);
 }
 
-const google::protobuf::FieldDescriptor* FindFieldWithOneofs(
-    const google::protobuf::Message* message, const char* field_name, bool* in_oneof) {
-  const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
-  const google::protobuf::FieldDescriptor* field_descriptor =
+const FieldDescriptor* FindFieldWithOneofs(
+    const Message* message, const string& field_name, bool* in_oneof) {
+  *in_oneof = false;
+  const Descriptor* descriptor = message->GetDescriptor();
+  const FieldDescriptor* field_descriptor =
       descriptor->FindFieldByName(field_name);
-  if (field_descriptor == NULL) {
-    const google::protobuf::OneofDescriptor* oneof_desc =
-      message->GetDescriptor()->FindOneofByName(field_name);
-    if (oneof_desc == NULL) {
-      *in_oneof = false;
-      return NULL;
-    } else {
-      *in_oneof = true;
-      return message->GetReflection()->GetOneofFieldDescriptor(
-          *message, oneof_desc);
+  if (field_descriptor != NULL) {
+    return field_descriptor;
+  }
+  const OneofDescriptor* oneof_desc =
+      descriptor->FindOneofByName(field_name);
+  if (oneof_desc != NULL) {
+    *in_oneof = true;
+    return message->GetReflection()->GetOneofFieldDescriptor(*message,
+                                                             oneof_desc);
+  }
+  return NULL;
+}
+
+bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
+  if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    PyErr_Format(PyExc_ValueError,
+                 "Protocol message has no singular \"%s\" field.",
+                 field_descriptor->name().c_str());
+    return false;
+  }
+
+  if (field_descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    // HasField() for a oneof *itself* isn't supported.
+    if (in_oneof) {
+      PyErr_Format(PyExc_ValueError,
+                   "Can't test oneof field \"%s\" for presence in proto3, use "
+                   "WhichOneof instead.",
+                   field_descriptor->containing_oneof()->name().c_str());
+      return false;
+    }
+
+    // ...but HasField() for fields *in* a oneof is supported.
+    if (field_descriptor->containing_oneof() != NULL) {
+      return true;
+    }
+
+    if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+      PyErr_Format(
+          PyExc_ValueError,
+          "Can't test non-submessage field \"%s\" for presence in proto3.",
+          field_descriptor->name().c_str());
+      return false;
     }
   }
-  return field_descriptor;
+
+  return true;
 }
 
 PyObject* HasField(CMessage* self, PyObject* arg) {
-#if PY_MAJOR_VERSION < 3
   char* field_name;
-  if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
-#else
-  char* field_name = PyUnicode_AsUTF8(arg);
-  if (!field_name) {
-#endif
+  Py_ssize_t size;
+#if PY_MAJOR_VERSION < 3
+  if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) {
     return NULL;
   }
+#else
+  field_name = PyUnicode_AsUTF8AndSize(arg, &size);
+  if (!field_name) {
+    return NULL;
+  }
+#endif
 
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+  Message* message = self->message;
   bool is_in_oneof;
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      FindFieldWithOneofs(message, field_name, &is_in_oneof);
+  const FieldDescriptor* field_descriptor =
+      FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
   if (field_descriptor == NULL) {
     if (!is_in_oneof) {
       PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
@@ -946,28 +977,28 @@
     }
   }
 
-  if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
-    PyErr_Format(PyExc_ValueError,
-                 "Protocol message has no singular \"%s\" field.", field_name);
+  if (!CheckHasPresence(field_descriptor, is_in_oneof)) {
     return NULL;
   }
 
-  bool has_field =
-      message->GetReflection()->HasField(*message, field_descriptor);
-  if (!has_field && field_descriptor->cpp_type() ==
-      google::protobuf::FieldDescriptor::CPPTYPE_ENUM) {
-    // We may have an invalid enum value stored in the UnknownFieldSet and need
-    // to check presence in there as well.
-    const google::protobuf::UnknownFieldSet& unknown_field_set =
+  if (message->GetReflection()->HasField(*message, field_descriptor)) {
+    Py_RETURN_TRUE;
+  }
+  if (!message->GetReflection()->SupportsUnknownEnumValues() &&
+      field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+    // Special case: Python HasField() differs in semantics from C++
+    // slightly: we return HasField('enum_field') == true if there is
+    // an unknown enum value present. To implement this we have to
+    // look in the UnknownFieldSet.
+    const UnknownFieldSet& unknown_field_set =
         message->GetReflection()->GetUnknownFields(*message);
     for (int i = 0; i < unknown_field_set.field_count(); ++i) {
       if (unknown_field_set.field(i).number() == field_descriptor->number()) {
         Py_RETURN_TRUE;
       }
     }
-    Py_RETURN_FALSE;
   }
-  return PyBool_FromLong(has_field ? 1 : 0);
+  Py_RETURN_FALSE;
 }
 
 PyObject* ClearExtension(CMessage* self, PyObject* arg) {
@@ -1034,7 +1065,7 @@
   }
 
   int VisitCMessage(CMessage* cmessage,
-                    const google::protobuf::FieldDescriptor* field_descriptor) {
+                    const FieldDescriptor* field_descriptor) {
     return SetOwner(cmessage, new_owner_);
   }
 
@@ -1053,18 +1084,17 @@
 // Releases the message specified by 'field' and returns the
 // pointer. If the field does not exist a new message is created using
 // 'descriptor'. The caller takes ownership of the returned pointer.
-Message* ReleaseMessage(google::protobuf::Message* message,
-                        const google::protobuf::Descriptor* descriptor,
-                        const google::protobuf::FieldDescriptor* field_descriptor) {
+Message* ReleaseMessage(Message* message,
+                        const Descriptor* descriptor,
+                        const FieldDescriptor* field_descriptor) {
   Message* released_message = message->GetReflection()->ReleaseMessage(
-      message, field_descriptor, global_message_factory);
+      message, field_descriptor, message_factory);
   // ReleaseMessage will return NULL which differs from
   // child_cmessage->message, if the field does not exist.  In this case,
   // the latter points to the default instance via a const_cast<>, so we
   // have to reset it to a new mutable object since we are taking ownership.
   if (released_message == NULL) {
-    const Message* prototype = global_message_factory->GetPrototype(
-        descriptor);
+    const Message* prototype = message_factory->GetPrototype(descriptor);
     GOOGLE_DCHECK(prototype != NULL);
     released_message = prototype->New();
   }
@@ -1072,8 +1102,8 @@
   return released_message;
 }
 
-int ReleaseSubMessage(google::protobuf::Message* message,
-                      const google::protobuf::FieldDescriptor* field_descriptor,
+int ReleaseSubMessage(Message* message,
+                      const FieldDescriptor* field_descriptor,
                       CMessage* child_cmessage) {
   // Release the Message
   shared_ptr<Message> released_message(ReleaseMessage(
@@ -1089,7 +1119,7 @@
 
 struct ReleaseChild : public ChildVisitor {
   // message must outlive this object.
-  explicit ReleaseChild(google::protobuf::Message* parent_message) :
+  explicit ReleaseChild(Message* parent_message) :
       parent_message_(parent_message) {}
 
   int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
@@ -1103,38 +1133,27 @@
   }
 
   int VisitCMessage(CMessage* cmessage,
-                    const google::protobuf::FieldDescriptor* field_descriptor) {
+                    const FieldDescriptor* field_descriptor) {
     return ReleaseSubMessage(parent_message_, field_descriptor,
         reinterpret_cast<CMessage*>(cmessage));
   }
 
-  google::protobuf::Message* parent_message_;
+  Message* parent_message_;
 };
 
 int InternalReleaseFieldByDescriptor(
-    const google::protobuf::FieldDescriptor* field_descriptor,
+    const FieldDescriptor* field_descriptor,
     PyObject* composite_field,
-    google::protobuf::Message* parent_message) {
+    Message* parent_message) {
   return VisitCompositeField(
       field_descriptor,
       composite_field,
       ReleaseChild(parent_message));
 }
 
-int InternalReleaseField(CMessage* self, PyObject* composite_field,
-                         PyObject* name) {
-  const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
-  if (descriptor != NULL) {
-    return InternalReleaseFieldByDescriptor(
-        descriptor, composite_field, self->message);
-  }
-
-  return 0;
-}
-
 PyObject* ClearFieldByDescriptor(
     CMessage* self,
-    const google::protobuf::FieldDescriptor* descriptor) {
+    const FieldDescriptor* descriptor) {
   if (!CheckFieldBelongsToMessage(descriptor, self->message)) {
     return NULL;
   }
@@ -1144,25 +1163,23 @@
 }
 
 PyObject* ClearField(CMessage* self, PyObject* arg) {
-  char* field_name;
   if (!PyString_Check(arg)) {
     PyErr_SetString(PyExc_TypeError, "field name must be a string");
     return NULL;
   }
 #if PY_MAJOR_VERSION < 3
-  if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
-    return NULL;
-  }
+  const char* field_name = PyString_AS_STRING(arg);
+  Py_ssize_t size = PyString_GET_SIZE(arg);
 #else
-  field_name = PyUnicode_AsUTF8(arg);
+  Py_ssize_t size;
+  const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size);
 #endif
   AssureWritable(self);
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+  Message* message = self->message;
   ScopedPyObjectPtr arg_in_oneof;
   bool is_in_oneof;
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      FindFieldWithOneofs(message, field_name, &is_in_oneof);
+  const FieldDescriptor* field_descriptor =
+      FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
   if (field_descriptor == NULL) {
     if (!is_in_oneof) {
       PyErr_Format(PyExc_ValueError,
@@ -1172,24 +1189,27 @@
       Py_RETURN_NONE;
     }
   } else if (is_in_oneof) {
-    arg_in_oneof.reset(PyString_FromString(field_descriptor->name().c_str()));
+    const string& name = field_descriptor->name();
+    arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size()));
     arg = arg_in_oneof.get();
   }
 
-  PyObject* composite_field = PyDict_GetItem(self->composite_fields,
-                                             arg);
+  PyObject* composite_field = self->composite_fields ?
+      PyDict_GetItem(self->composite_fields, arg) : NULL;
 
   // Only release the field if there's a possibility that there are
   // references to it.
   if (composite_field != NULL) {
-    if (InternalReleaseField(self, composite_field, arg) < 0) {
+    if (InternalReleaseFieldByDescriptor(field_descriptor,
+                                         composite_field, message) < 0) {
       return NULL;
     }
     PyDict_DelItem(self->composite_fields, arg);
   }
   message->GetReflection()->ClearField(message, field_descriptor);
-  if (field_descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) {
-    google::protobuf::UnknownFieldSet* unknown_field_set =
+  if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+      !message->GetReflection()->SupportsUnknownEnumValues()) {
+    UnknownFieldSet* unknown_field_set =
         message->GetReflection()->MutableUnknownFields(message);
     unknown_field_set->DeleteByNumber(field_descriptor->number());
   }
@@ -1212,7 +1232,9 @@
     }
     self->extensions = extension_dict;
   }
-  PyDict_Clear(self->composite_fields);
+  if (self->composite_fields) {
+    PyDict_Clear(self->composite_fields);
+  }
   self->message->Clear();
   Py_RETURN_NONE;
 }
@@ -1242,7 +1264,27 @@
     if (joined == NULL) {
       return NULL;
     }
-    PyErr_Format(EncodeError_class, "Message %s is missing required fields: %s",
+
+    // TODO(haberman): this is a (hopefully temporary) hack.  The unit testing
+    // infrastructure reloads all pure-Python modules for every test, but not
+    // C++ modules (because that's generally impossible:
+    // http://bugs.python.org/issue1144263).  But if we cache EncodeError, we'll
+    // return the EncodeError from a previous load of the module, which won't
+    // match a user's attempt to catch EncodeError.  So we have to look it up
+    // again every time.
+    ScopedPyObjectPtr message_module(PyImport_ImportModule(
+        "google.protobuf.message"));
+    if (message_module.get() == NULL) {
+      return NULL;
+    }
+
+    ScopedPyObjectPtr encode_error(
+        PyObject_GetAttrString(message_module, "EncodeError"));
+    if (encode_error.get() == NULL) {
+      return NULL;
+    }
+    PyErr_Format(encode_error.get(),
+                 "Message %s is missing required fields: %s",
                  GetMessageName(self).c_str(), PyString_AsString(joined));
     return NULL;
   }
@@ -1268,7 +1310,7 @@
 
 // Formats proto fields for ascii dumps using python formatting functions where
 // appropriate.
-class PythonFieldValuePrinter : public google::protobuf::TextFormat::FieldValuePrinter {
+class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter {
  public:
   PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {}
 
@@ -1301,7 +1343,7 @@
 };
 
 static PyObject* ToStr(CMessage* self) {
-  google::protobuf::TextFormat::Printer printer;
+  TextFormat::Printer printer;
   // Passes ownership
   printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter());
   printer.SetHideUnknownFields(true);
@@ -1383,9 +1425,9 @@
   }
 
   AssureWritable(self);
-  google::protobuf::io::CodedInputStream input(
+  io::CodedInputStream input(
       reinterpret_cast<const uint8*>(data), data_length);
-  input.SetExtensionRegistry(descriptor_pool->pool, global_message_factory);
+  input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory);
   bool success = self->message->MergePartialFromCodedStream(&input);
   if (success) {
     return PyInt_FromLong(input.CurrentPosition());
@@ -1412,10 +1454,22 @@
   if (message_descriptor == NULL) {
     return NULL;
   }
-  if (PyObject_SetAttrString(extension_handle, "containing_type",
-                             message_descriptor) < 0) {
+
+  const FieldDescriptor* descriptor =
+      GetExtensionDescriptor(extension_handle);
+  if (descriptor == NULL) {
     return NULL;
   }
+  const Descriptor* cmessage_descriptor = GetMessageDescriptor(
+      reinterpret_cast<PyTypeObject*>(cls));
+
+  if (cmessage_descriptor != descriptor->containing_type()) {
+    if (PyObject_SetAttrString(extension_handle, "containing_type",
+                               message_descriptor) < 0) {
+      return NULL;
+    }
+  }
+
   ScopedPyObjectPtr extensions_by_name(
       PyObject_GetAttr(cls, k_extensions_by_name));
   if (extensions_by_name == NULL) {
@@ -1426,6 +1480,20 @@
   if (full_name == NULL) {
     return NULL;
   }
+
+  // If the extension was already registered, check that it is the same.
+  PyObject* existing_extension = PyDict_GetItem(extensions_by_name, full_name);
+  if (existing_extension != NULL) {
+    const FieldDescriptor* existing_extension_descriptor =
+        GetExtensionDescriptor(existing_extension);
+    if (existing_extension_descriptor != descriptor) {
+      PyErr_SetString(PyExc_ValueError, "Double registration of Extensions");
+      return NULL;
+    }
+    // Nothing else to do.
+    Py_RETURN_NONE;
+  }
+
   if (PyDict_SetItem(extensions_by_name, full_name, extension_handle) < 0) {
     return NULL;
   }
@@ -1445,17 +1513,12 @@
     return NULL;
   }
 
-  const google::protobuf::FieldDescriptor* descriptor =
-      GetExtensionDescriptor(extension_handle);
-  if (descriptor == NULL) {
-    return NULL;
-  }
   // Check if it's a message set
   if (descriptor->is_extension() &&
       descriptor->containing_type()->options().message_set_wire_format() &&
-      descriptor->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE &&
+      descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
       descriptor->message_type() == descriptor->extension_scope() &&
-      descriptor->label() == google::protobuf::FieldDescriptor::LABEL_OPTIONAL) {
+      descriptor->label() == FieldDescriptor::LABEL_OPTIONAL) {
     ScopedPyObjectPtr message_name(PyString_FromStringAndSize(
         descriptor->message_type()->full_name().c_str(),
         descriptor->message_type()->full_name().size()));
@@ -1474,53 +1537,36 @@
 }
 
 static PyObject* WhichOneof(CMessage* self, PyObject* arg) {
-  char* oneof_name;
-  if (!PyString_Check(arg)) {
-    PyErr_SetString(PyExc_TypeError, "field name must be a string");
+  Py_ssize_t name_size;
+  char *name_data;
+  if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0)
     return NULL;
-  }
-  oneof_name = PyString_AsString(arg);
-  if (oneof_name == NULL) {
-    return NULL;
-  }
-  const google::protobuf::OneofDescriptor* oneof_desc =
+  string oneof_name = string(name_data, name_size);
+  const OneofDescriptor* oneof_desc =
       self->message->GetDescriptor()->FindOneofByName(oneof_name);
   if (oneof_desc == NULL) {
     PyErr_Format(PyExc_ValueError,
-                 "Protocol message has no oneof \"%s\" field.", oneof_name);
+                 "Protocol message has no oneof \"%s\" field.",
+                 oneof_name.c_str());
     return NULL;
   }
-  const google::protobuf::FieldDescriptor* field_in_oneof =
+  const FieldDescriptor* field_in_oneof =
       self->message->GetReflection()->GetOneofFieldDescriptor(
           *self->message, oneof_desc);
   if (field_in_oneof == NULL) {
     Py_RETURN_NONE;
   } else {
-    return PyString_FromString(field_in_oneof->name().c_str());
+    const string& name = field_in_oneof->name();
+    return PyString_FromStringAndSize(name.c_str(), name.size());
   }
 }
 
 static PyObject* ListFields(CMessage* self) {
-  vector<const google::protobuf::FieldDescriptor*> fields;
+  vector<const FieldDescriptor*> fields;
   self->message->GetReflection()->ListFields(*self->message, &fields);
 
-  PyObject* descriptor = PyDict_GetItem(Py_TYPE(self)->tp_dict, kDESCRIPTOR);
-  if (descriptor == NULL) {
-    return NULL;
-  }
-  ScopedPyObjectPtr fields_by_name(
-      PyObject_GetAttr(descriptor, kfields_by_name));
-  if (fields_by_name == NULL) {
-    return NULL;
-  }
-  ScopedPyObjectPtr extensions_by_name(PyObject_GetAttr(
-      reinterpret_cast<PyObject*>(Py_TYPE(self)), k_extensions_by_name));
-  if (extensions_by_name == NULL) {
-    PyErr_SetString(PyExc_ValueError, "no extensionsbyname");
-    return NULL;
-  }
   // Normally, the list will be exactly the size of the fields.
-  PyObject* all_fields = PyList_New(fields.size());
+  ScopedPyObjectPtr all_fields(PyList_New(fields.size()));
   if (all_fields == NULL) {
     return NULL;
   }
@@ -1532,35 +1578,34 @@
   for (Py_ssize_t i = 0; i < fields.size(); ++i) {
     ScopedPyObjectPtr t(PyTuple_New(2));
     if (t == NULL) {
-      Py_DECREF(all_fields);
       return NULL;
     }
 
     if (fields[i]->is_extension()) {
-      const string& field_name = fields[i]->full_name();
-      PyObject* extension_field = PyDict_GetItemString(extensions_by_name,
-                                                       field_name.c_str());
+      ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(fields[i]));
       if (extension_field == NULL) {
-        // If we couldn't fetch extension_field, it means the module that
-        // defines this extension has not been explicitly imported in Python
-        // code, and the extension hasn't been registered. There's nothing much
-        // we can do about this, so just skip it in the output to match the
-        // behavior of the python implementation.
+        return NULL;
+      }
+      // With C++ descriptors, the field can always be retrieved, but for
+      // unknown extensions which have not been imported in Python code, there
+      // is no message class and we cannot retrieve the value.
+      // TODO(amauryfa): consider building the class on the fly!
+      if (fields[i]->message_type() != NULL &&
+          cdescriptor_pool::GetMessageClass(
+              GetDescriptorPool(), fields[i]->message_type()) == NULL) {
+        PyErr_Clear();
         continue;
       }
       PyObject* extensions = reinterpret_cast<PyObject*>(self->extensions);
       if (extensions == NULL) {
-        Py_DECREF(all_fields);
         return NULL;
       }
       // 'extension' reference later stolen by PyTuple_SET_ITEM.
       PyObject* extension = PyObject_GetItem(extensions, extension_field);
       if (extension == NULL) {
-        Py_DECREF(all_fields);
         return NULL;
       }
-      Py_INCREF(extension_field);
-      PyTuple_SET_ITEM(t.get(), 0, extension_field);
+      PyTuple_SET_ITEM(t.get(), 0, extension_field.release());
       // Steals reference to 'extension'
       PyTuple_SET_ITEM(t.get(), 1, extension);
     } else {
@@ -1569,35 +1614,30 @@
           field_name.c_str(), field_name.length()));
       if (py_field_name == NULL) {
         PyErr_SetString(PyExc_ValueError, "bad string");
-        Py_DECREF(all_fields);
         return NULL;
       }
-      PyObject* field_descriptor =
-          PyDict_GetItem(fields_by_name, py_field_name);
+      ScopedPyObjectPtr field_descriptor(PyFieldDescriptor_New(fields[i]));
       if (field_descriptor == NULL) {
-        Py_DECREF(all_fields);
         return NULL;
       }
 
       PyObject* field_value = GetAttr(self, py_field_name);
       if (field_value == NULL) {
         PyErr_SetObject(PyExc_ValueError, py_field_name);
-        Py_DECREF(all_fields);
         return NULL;
       }
-      Py_INCREF(field_descriptor);
-      PyTuple_SET_ITEM(t.get(), 0, field_descriptor);
+      PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release());
       PyTuple_SET_ITEM(t.get(), 1, field_value);
     }
-    PyList_SET_ITEM(all_fields, actual_size, t.release());
+    PyList_SET_ITEM(all_fields.get(), actual_size, t.release());
     ++actual_size;
   }
-  Py_SIZE(all_fields) = actual_size;
-  return all_fields;
+  Py_SIZE(all_fields.get()) = actual_size;
+  return all_fields.release();
 }
 
 PyObject* FindInitializationErrors(CMessage* self) {
-  google::protobuf::Message* message = self->message;
+  Message* message = self->message;
   vector<string> errors;
   message->FindInitializationErrors(&errors);
 
@@ -1645,9 +1685,9 @@
 
 PyObject* InternalGetScalar(
     CMessage* self,
-    const google::protobuf::FieldDescriptor* field_descriptor) {
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+    const FieldDescriptor* field_descriptor) {
+  Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
 
   if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
     return NULL;
@@ -1655,50 +1695,51 @@
 
   PyObject* result = NULL;
   switch (field_descriptor->cpp_type()) {
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+    case FieldDescriptor::CPPTYPE_INT32: {
       int32 value = reflection->GetInt32(*message, field_descriptor);
       result = PyInt_FromLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+    case FieldDescriptor::CPPTYPE_INT64: {
       int64 value = reflection->GetInt64(*message, field_descriptor);
       result = PyLong_FromLongLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+    case FieldDescriptor::CPPTYPE_UINT32: {
       uint32 value = reflection->GetUInt32(*message, field_descriptor);
       result = PyInt_FromSize_t(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+    case FieldDescriptor::CPPTYPE_UINT64: {
       uint64 value = reflection->GetUInt64(*message, field_descriptor);
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+    case FieldDescriptor::CPPTYPE_FLOAT: {
       float value = reflection->GetFloat(*message, field_descriptor);
       result = PyFloat_FromDouble(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = reflection->GetDouble(*message, field_descriptor);
       result = PyFloat_FromDouble(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+    case FieldDescriptor::CPPTYPE_BOOL: {
       bool value = reflection->GetBool(*message, field_descriptor);
       result = PyBool_FromLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+    case FieldDescriptor::CPPTYPE_STRING: {
       string value = reflection->GetString(*message, field_descriptor);
       result = ToStringObject(field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
-      if (!message->GetReflection()->HasField(*message, field_descriptor)) {
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      if (!message->GetReflection()->SupportsUnknownEnumValues() &&
+          !message->GetReflection()->HasField(*message, field_descriptor)) {
         // Look for the value in the unknown fields.
-        google::protobuf::UnknownFieldSet* unknown_field_set =
+        UnknownFieldSet* unknown_field_set =
             message->GetReflection()->MutableUnknownFields(message);
         for (int i = 0; i < unknown_field_set->field_count(); ++i) {
           if (unknown_field_set->field(i).number() ==
@@ -1710,7 +1751,7 @@
       }
 
       if (result == NULL) {
-        const google::protobuf::EnumValueDescriptor* enum_value =
+        const EnumValueDescriptor* enum_value =
             message->GetReflection()->GetEnum(*message, field_descriptor);
         result = PyInt_FromLong(enum_value->number());
       }
@@ -1726,13 +1767,13 @@
 }
 
 PyObject* InternalGetSubMessage(
-    CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) {
-  const google::protobuf::Reflection* reflection = self->message->GetReflection();
-  const google::protobuf::Message& sub_message = reflection->GetMessage(
-      *self->message, field_descriptor, global_message_factory);
+    CMessage* self, const FieldDescriptor* field_descriptor) {
+  const Reflection* reflection = self->message->GetReflection();
+  const Message& sub_message = reflection->GetMessage(
+      *self->message, field_descriptor, message_factory);
 
   PyObject *message_class = cdescriptor_pool::GetMessageClass(
-      descriptor_pool, field_descriptor->message_type());
+      GetDescriptorPool(), field_descriptor->message_type());
   if (message_class == NULL) {
     return NULL;
   }
@@ -1747,17 +1788,17 @@
   cmsg->parent = self;
   cmsg->parent_field_descriptor = field_descriptor;
   cmsg->read_only = !reflection->HasField(*self->message, field_descriptor);
-  cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
+  cmsg->message = const_cast<Message*>(&sub_message);
 
   return reinterpret_cast<PyObject*>(cmsg);
 }
 
 int InternalSetScalar(
     CMessage* self,
-    const google::protobuf::FieldDescriptor* field_descriptor,
+    const FieldDescriptor* field_descriptor,
     PyObject* arg) {
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
 
   if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
     return -1;
@@ -1768,59 +1809,62 @@
   }
 
   switch (field_descriptor->cpp_type()) {
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+    case FieldDescriptor::CPPTYPE_INT32: {
       GOOGLE_CHECK_GET_INT32(arg, value, -1);
       reflection->SetInt32(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+    case FieldDescriptor::CPPTYPE_INT64: {
       GOOGLE_CHECK_GET_INT64(arg, value, -1);
       reflection->SetInt64(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+    case FieldDescriptor::CPPTYPE_UINT32: {
       GOOGLE_CHECK_GET_UINT32(arg, value, -1);
       reflection->SetUInt32(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+    case FieldDescriptor::CPPTYPE_UINT64: {
       GOOGLE_CHECK_GET_UINT64(arg, value, -1);
       reflection->SetUInt64(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+    case FieldDescriptor::CPPTYPE_FLOAT: {
       GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
       reflection->SetFloat(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
       GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
       reflection->SetDouble(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+    case FieldDescriptor::CPPTYPE_BOOL: {
       GOOGLE_CHECK_GET_BOOL(arg, value, -1);
       reflection->SetBool(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+    case FieldDescriptor::CPPTYPE_STRING: {
       if (!CheckAndSetString(
           arg, message, field_descriptor, reflection, false, -1)) {
         return -1;
       }
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+    case FieldDescriptor::CPPTYPE_ENUM: {
       GOOGLE_CHECK_GET_INT32(arg, value, -1);
-      const google::protobuf::EnumDescriptor* enum_descriptor =
-          field_descriptor->enum_type();
-      const google::protobuf::EnumValueDescriptor* enum_value =
-          enum_descriptor->FindValueByNumber(value);
-      if (enum_value != NULL) {
-        reflection->SetEnum(message, field_descriptor, enum_value);
+      if (reflection->SupportsUnknownEnumValues()) {
+        reflection->SetEnumValue(message, field_descriptor, value);
       } else {
-        PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
-        return -1;
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          reflection->SetEnum(message, field_descriptor, enum_value);
+        } else {
+          PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
+          return -1;
+        }
       }
       break;
     }
@@ -1851,14 +1895,35 @@
   return py_cmsg;
 }
 
+// Add the number of a field descriptor to the containing message class.
+// Equivalent to:
+//   _cls.<field>_FIELD_NUMBER = <number>
+static bool AddFieldNumberToClass(
+    PyObject* cls, const FieldDescriptor* field_descriptor) {
+  string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
+  UpperString(&constant_name);
+  ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
+      constant_name.c_str(), constant_name.size()));
+  if (attr_name == NULL) {
+    return false;
+  }
+  ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
+  if (number == NULL) {
+    return false;
+  }
+  if (PyObject_SetAttr(cls, attr_name, number) == -1) {
+    return false;
+  }
+  return true;
+}
+
 
 // Finalize the creation of the Message class.
 // Called from its metaclass: GeneratedProtocolMessageType.__init__().
-static PyObject* AddDescriptors(PyTypeObject* cls,
-                                PyObject* descriptor) {
-  const google::protobuf::Descriptor* message_descriptor =
+static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) {
+  const Descriptor* message_descriptor =
       cdescriptor_pool::RegisterMessageClass(
-          descriptor_pool, reinterpret_cast<PyObject*>(cls), descriptor);
+          GetDescriptorPool(), cls, descriptor);
   if (message_descriptor == NULL) {
     return NULL;
   }
@@ -1867,169 +1932,80 @@
   // classes will register themselves in this class.
   if (message_descriptor->extension_range_count() > 0) {
     ScopedPyObjectPtr by_name(PyDict_New());
-    if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                         k_extensions_by_name, by_name) < 0) {
+    if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
       return NULL;
     }
     ScopedPyObjectPtr by_number(PyDict_New());
-    if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                         k_extensions_by_number, by_number) < 0) {
+    if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
       return NULL;
     }
   }
 
-  ScopedPyObjectPtr fields(PyObject_GetAttrString(descriptor, "fields"));
-  if (fields == NULL) {
-    return NULL;
-  }
-
-  ScopedPyObjectPtr _NUMBER_string(PyString_FromString("_FIELD_NUMBER"));
-  if (_NUMBER_string == NULL) {
-    return NULL;
-  }
-
-  const Py_ssize_t fields_size = PyList_GET_SIZE(fields.get());
-  for (int i = 0; i < fields_size; ++i) {
-    PyObject* field = PyList_GET_ITEM(fields.get(), i);
-    ScopedPyObjectPtr field_name(PyObject_GetAttr(field, kname));
-    ScopedPyObjectPtr full_field_name(PyObject_GetAttr(field, kfull_name));
-    if (field_name == NULL || full_field_name == NULL) {
-      PyErr_SetString(PyExc_TypeError, "Name is null");
-      return NULL;
-    }
-
-    ScopedPyObjectPtr field_descriptor(
-        cdescriptor_pool::FindFieldByName(descriptor_pool, full_field_name));
-    if (field_descriptor == NULL) {
-      PyErr_SetString(PyExc_TypeError, "Couldn't find field");
-      return NULL;
-    }
-    CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(
-        field_descriptor.get());
-
-    // The FieldDescriptor's name field might either be of type bytes or
-    // of type unicode, depending on whether the FieldDescriptor was
-    // parsed from a serialized message or read from the
-    // <message>_pb2.py module.
-    ScopedPyObjectPtr field_name_upcased(
-         PyObject_CallMethod(field_name, "upper", NULL));
-    if (field_name_upcased == NULL) {
-      return NULL;
-    }
-
-    ScopedPyObjectPtr field_number_name(PyObject_CallMethod(
-         field_name_upcased, "__add__", "(O)", _NUMBER_string.get()));
-    if (field_number_name == NULL) {
-      return NULL;
-    }
-
-    ScopedPyObjectPtr number(PyInt_FromLong(
-        cfield_descriptor->descriptor->number()));
-    if (number == NULL) {
-      return NULL;
-    }
-    if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                         field_number_name, number) == -1) {
+  // For each field set: cls.<field>_FIELD_NUMBER = <number>
+  for (int i = 0; i < message_descriptor->field_count(); ++i) {
+    if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
       return NULL;
     }
   }
 
-  // Enum Values
-  ScopedPyObjectPtr enum_types(PyObject_GetAttrString(descriptor,
-                                                      "enum_types"));
-  if (enum_types == NULL) {
-    return NULL;
-  }
-  ScopedPyObjectPtr type_iter(PyObject_GetIter(enum_types));
-  if (type_iter == NULL) {
-    return NULL;
-  }
-  ScopedPyObjectPtr enum_type;
-  while ((enum_type.reset(PyIter_Next(type_iter))) != NULL) {
+  // For each enum set cls.<enum name> = EnumTypeWrapper(<enum descriptor>).
+  //
+  // The enum descriptor we get from
+  // <messagedescriptor>.enum_types_by_name[name]
+  // which was built previously.
+  for (int i = 0; i < message_descriptor->enum_type_count(); ++i) {
+    const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
+    ScopedPyObjectPtr enum_type(PyEnumDescriptor_New(enum_descriptor));
+    if (enum_type == NULL) {
+      return NULL;
+     }
+    // Add wrapped enum type to message class.
     ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
         EnumTypeWrapper_class, enum_type.get(), NULL));
     if (wrapped == NULL) {
       return NULL;
     }
-    ScopedPyObjectPtr enum_name(PyObject_GetAttr(enum_type, kname));
-    if (enum_name == NULL) {
-      return NULL;
-    }
-    if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                         enum_name, wrapped) == -1) {
+    if (PyObject_SetAttrString(
+            cls, enum_descriptor->name().c_str(), wrapped) == -1) {
       return NULL;
     }
 
-    ScopedPyObjectPtr enum_values(PyObject_GetAttrString(enum_type, "values"));
-    if (enum_values == NULL) {
-      return NULL;
-    }
-    ScopedPyObjectPtr values_iter(PyObject_GetIter(enum_values));
-    if (values_iter == NULL) {
-      return NULL;
-    }
-    ScopedPyObjectPtr enum_value;
-    while ((enum_value.reset(PyIter_Next(values_iter))) != NULL) {
-      ScopedPyObjectPtr value_name(PyObject_GetAttr(enum_value, kname));
-      if (value_name == NULL) {
-        return NULL;
-      }
-      ScopedPyObjectPtr value_number(PyObject_GetAttrString(enum_value,
-                                                            "number"));
+    // For each enum value add cls.<name> = <number>
+    for (int j = 0; j < enum_descriptor->value_count(); ++j) {
+      const EnumValueDescriptor* enum_value_descriptor =
+          enum_descriptor->value(j);
+      ScopedPyObjectPtr value_number(PyInt_FromLong(
+          enum_value_descriptor->number()));
       if (value_number == NULL) {
         return NULL;
       }
-      if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                           value_name, value_number) == -1) {
+      if (PyObject_SetAttrString(
+              cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
         return NULL;
       }
     }
-    if (PyErr_Occurred()) {  // If PyIter_Next failed
-      return NULL;
-    }
-  }
-  if (PyErr_Occurred()) {  // If PyIter_Next failed
-    return NULL;
   }
 
-  ScopedPyObjectPtr extension_dict(
-      PyObject_GetAttr(descriptor, kextensions_by_name));
-  if (extension_dict == NULL || !PyDict_Check(extension_dict)) {
-    PyErr_SetString(PyExc_TypeError, "extensions_by_name not a dict");
-    return NULL;
-  }
-  Py_ssize_t pos = 0;
-  PyObject* extension_name;
-  PyObject* extension_field;
-
-  while (PyDict_Next(extension_dict, &pos, &extension_name, &extension_field)) {
-    if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                         extension_name, extension_field) == -1) {
-      return NULL;
-    }
-    const google::protobuf::FieldDescriptor* field_descriptor =
-        GetExtensionDescriptor(extension_field);
-    if (field_descriptor == NULL) {
+  // For each extension set cls.<extension name> = <extension descriptor>.
+  //
+  // Extension descriptors come from
+  // <message descriptor>.extensions_by_name[name]
+  // which was defined previously.
+  for (int i = 0; i < message_descriptor->extension_count(); ++i) {
+    const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
+    ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(field));
+    if (extension_field == NULL) {
       return NULL;
     }
 
-    ScopedPyObjectPtr field_name_upcased(
-        PyObject_CallMethod(extension_name, "upper", NULL));
-    if (field_name_upcased == NULL) {
+    // Add the extension field to the message class.
+    if (PyObject_SetAttrString(
+            cls, field->name().c_str(), extension_field) == -1) {
       return NULL;
     }
-    ScopedPyObjectPtr field_number_name(PyObject_CallMethod(
-         field_name_upcased, "__add__", "(O)", _NUMBER_string.get()));
-    if (field_number_name == NULL) {
-      return NULL;
-    }
-    ScopedPyObjectPtr number(PyInt_FromLong(
-        field_descriptor->number()));
-    if (number == NULL) {
-      return NULL;
-    }
-    if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
-                         field_number_name, number) == -1) {
+
+    // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
+    if (!AddFieldNumberToClass(cls, field)) {
       return NULL;
     }
   }
@@ -2121,12 +2097,35 @@
 }
 
 // CMessage static methods:
+PyObject* _GetMessageDescriptor(PyObject* unused, PyObject* arg) {
+  return cdescriptor_pool::FindMessageByName(GetDescriptorPool(), arg);
+}
+
 PyObject* _GetFieldDescriptor(PyObject* unused, PyObject* arg) {
-  return cdescriptor_pool::FindFieldByName(descriptor_pool, arg);
+  return cdescriptor_pool::FindFieldByName(GetDescriptorPool(), arg);
 }
 
 PyObject* _GetExtensionDescriptor(PyObject* unused, PyObject* arg) {
-  return cdescriptor_pool::FindExtensionByName(descriptor_pool, arg);
+  return cdescriptor_pool::FindExtensionByName(GetDescriptorPool(), arg);
+}
+
+PyObject* _GetEnumDescriptor(PyObject* unused, PyObject* arg) {
+  return cdescriptor_pool::FindEnumTypeByName(GetDescriptorPool(), arg);
+}
+
+PyObject* _GetOneofDescriptor(PyObject* unused, PyObject* arg) {
+  return cdescriptor_pool::FindOneofByName(GetDescriptorPool(), arg);
+}
+
+PyObject* _CheckCalledFromGeneratedFile(PyObject* unused,
+                                        PyObject* unused_arg) {
+  if (!_CalledFromGeneratedFile(1)) {
+    PyErr_SetString(PyExc_TypeError,
+                    "Descriptors should not be created directly, "
+                    "but only retrieved from their parent.");
+    return NULL;
+  }
+  Py_RETURN_NONE;
 }
 
 static PyMemberDef Members[] = {
@@ -2191,91 +2190,102 @@
   // Static Methods.
   { "_BuildFile", (PyCFunction)Python_BuildFile, METH_O | METH_STATIC,
     "Registers a new protocol buffer file in the global C++ descriptor pool." },
+  { "_GetMessageDescriptor", (PyCFunction)_GetMessageDescriptor,
+    METH_O | METH_STATIC, "Finds a message descriptor in the message pool." },
   { "_GetFieldDescriptor", (PyCFunction)_GetFieldDescriptor,
     METH_O | METH_STATIC, "Finds a field descriptor in the message pool." },
   { "_GetExtensionDescriptor", (PyCFunction)_GetExtensionDescriptor,
     METH_O | METH_STATIC,
     "Finds a extension descriptor in the message pool." },
+  { "_GetEnumDescriptor", (PyCFunction)_GetEnumDescriptor,
+    METH_O | METH_STATIC,
+    "Finds an enum descriptor in the message pool." },
+  { "_GetOneofDescriptor", (PyCFunction)_GetOneofDescriptor,
+    METH_O | METH_STATIC,
+    "Finds an oneof descriptor in the message pool." },
+  { "_CheckCalledFromGeneratedFile", (PyCFunction)_CheckCalledFromGeneratedFile,
+    METH_NOARGS | METH_STATIC,
+    "Raises TypeError if the caller is not in a _pb2.py file."},
   { NULL, NULL}
 };
 
+static bool SetCompositeField(
+    CMessage* self, PyObject* name, PyObject* value) {
+  if (self->composite_fields == NULL) {
+    self->composite_fields = PyDict_New();
+    if (self->composite_fields == NULL) {
+      return false;
+    }
+  }
+  return PyDict_SetItem(self->composite_fields, name, value) == 0;
+}
+
 PyObject* GetAttr(CMessage* self, PyObject* name) {
-  PyObject* value = PyDict_GetItem(self->composite_fields, name);
+  PyObject* value = self->composite_fields ?
+      PyDict_GetItem(self->composite_fields, name) : NULL;
   if (value != NULL) {
     Py_INCREF(value);
     return value;
   }
 
-  const google::protobuf::FieldDescriptor* field_descriptor = GetFieldDescriptor(
-      self, name);
-  if (field_descriptor != NULL) {
-    if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
-      if (field_descriptor->cpp_type() ==
-          google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
-        PyObject *message_class = cdescriptor_pool::GetMessageClass(
-            descriptor_pool, field_descriptor->message_type());
-        if (message_class == NULL) {
-          return NULL;
-        }
-        PyObject* py_container = repeated_composite_container::NewContainer(
-            self, field_descriptor, message_class);
-        if (py_container == NULL) {
-          return NULL;
-        }
-        if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) {
-          Py_DECREF(py_container);
-          return NULL;
-        }
-        return py_container;
-      } else {
-        PyObject* py_container = repeated_scalar_container::NewContainer(
-            self, field_descriptor);
-        if (py_container == NULL) {
-          return NULL;
-        }
-        if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) {
-          Py_DECREF(py_container);
-          return NULL;
-        }
-        return py_container;
-      }
-    } else {
-      if (field_descriptor->cpp_type() ==
-          google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
-        PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
-        if (PyDict_SetItem(self->composite_fields, name, sub_message) < 0) {
-          Py_DECREF(sub_message);
-          return NULL;
-        }
-        return sub_message;
-      } else {
-        return InternalGetScalar(self, field_descriptor);
-      }
-    }
+  const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name);
+  if (field_descriptor == NULL) {
+    return CMessage_Type.tp_base->tp_getattro(
+        reinterpret_cast<PyObject*>(self), name);
   }
 
-  return CMessage_Type.tp_base->tp_getattro(reinterpret_cast<PyObject*>(self),
-                                            name);
+  if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    PyObject* py_container = NULL;
+    if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      PyObject *message_class = cdescriptor_pool::GetMessageClass(
+          GetDescriptorPool(), field_descriptor->message_type());
+      if (message_class == NULL) {
+        return NULL;
+      }
+      py_container = repeated_composite_container::NewContainer(
+          self, field_descriptor, message_class);
+    } else {
+      py_container = repeated_scalar_container::NewContainer(
+          self, field_descriptor);
+    }
+    if (py_container == NULL) {
+      return NULL;
+    }
+    if (!SetCompositeField(self, name, py_container)) {
+      Py_DECREF(py_container);
+      return NULL;
+    }
+    return py_container;
+  }
+
+  if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
+    if (!SetCompositeField(self, name, sub_message)) {
+      Py_DECREF(sub_message);
+      return NULL;
+    }
+    return sub_message;
+  }
+
+  return InternalGetScalar(self, field_descriptor);
 }
 
 int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
-  if (PyDict_Contains(self->composite_fields, name)) {
+  if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) {
     PyErr_SetString(PyExc_TypeError, "Can't set composite field");
     return -1;
   }
 
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      GetFieldDescriptor(self, name);
+  const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name);
   if (field_descriptor != NULL) {
     AssureWritable(self);
-    if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
+    if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
       PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated "
                    "field \"%s\" in protocol message object.",
                    field_descriptor->name().c_str());
       return -1;
     } else {
-      if (field_descriptor->cpp_type() ==
-          google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
         PyErr_Format(PyExc_AttributeError, "Assignment not allowed to "
                      "field \"%s\" in protocol message object.",
                      field_descriptor->name().c_str());
@@ -2294,8 +2304,9 @@
 
 PyTypeObject CMessage_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  "google.protobuf.internal."
-  "cpp._message.CMessage",             // tp_name
+  // Keep the fully qualified _message symbol in a line for opensource.
+  "google.protobuf.pyext._message."
+  "CMessage",                          // tp_name
   sizeof(CMessage),                    // tp_basicsize
   0,                                   //  tp_itemsize
   (destructor)cmessage::Dealloc,       //  tp_dealloc
@@ -2339,7 +2350,7 @@
 const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg);
 Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg);
 
-static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
+static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
   if (!PyObject_TypeCheck(msg, &CMessage_Type)) {
     return NULL;
   }
@@ -2347,12 +2358,12 @@
   return cmsg->message;
 }
 
-static google::protobuf::Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
+static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
   if (!PyObject_TypeCheck(msg, &CMessage_Type)) {
     return NULL;
   }
   CMessage* cmsg = reinterpret_cast<CMessage*>(msg);
-  if (PyDict_Size(cmsg->composite_fields) != 0 ||
+  if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) ||
       (cmsg->extensions != NULL &&
        PyDict_Size(cmsg->extensions->values) != 0)) {
     // There is currently no way of accurately syncing arbitrary changes to
@@ -2387,29 +2398,35 @@
   kDESCRIPTOR = PyString_FromString("DESCRIPTOR");
   k_cdescriptor = PyString_FromString("_cdescriptor");
   kfull_name = PyString_FromString("full_name");
-  kextensions_by_name = PyString_FromString("extensions_by_name");
   k_extensions_by_name = PyString_FromString("_extensions_by_name");
   k_extensions_by_number = PyString_FromString("_extensions_by_number");
-  kname = PyString_FromString("name");
-  kfields_by_name = PyString_FromString("fields_by_name");
 
-  descriptor_pool = cdescriptor_pool::NewDescriptorPool();
-
-  global_message_factory = new DynamicMessageFactory(descriptor_pool->pool);
-  global_message_factory->SetDelegateToGeneratedFactory(true);
+  message_factory = new DynamicMessageFactory(GetDescriptorPool()->pool);
+  message_factory->SetDelegateToGeneratedFactory(true);
 }
 
 bool InitProto2MessageModule(PyObject *m) {
+  // Initialize types and globals in descriptor.cc
+  if (!InitDescriptor()) {
+    return false;
+  }
+
+  // Initialize types and globals in descriptor_pool.cc
+  if (!InitDescriptorPool()) {
+    return false;
+  }
+
+  // Initialize constants defined in this file.
   InitGlobals();
 
-  google::protobuf::python::CMessage_Type.tp_hash = PyObject_HashNotImplemented;
-  if (PyType_Ready(&google::protobuf::python::CMessage_Type) < 0) {
+  CMessage_Type.tp_hash = PyObject_HashNotImplemented;
+  if (PyType_Ready(&CMessage_Type) < 0) {
     return false;
   }
 
   // DESCRIPTOR is set on each protocol buffer message class elsewhere, but set
   // it here as well to document that subclasses need to set it.
-  PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
+  PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
   // Subclasses with message extensions will override _extensions_by_name and
   // _extensions_by_number with fresh mutable dictionaries in AddDescriptors.
   // All other classes can share this same immutable mapping.
@@ -2421,58 +2438,69 @@
   if (immutable_dict == NULL) {
     return false;
   }
-  if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
+  if (PyDict_SetItem(CMessage_Type.tp_dict,
                      k_extensions_by_name, immutable_dict) < 0) {
     return false;
   }
-  if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
+  if (PyDict_SetItem(CMessage_Type.tp_dict,
                      k_extensions_by_number, immutable_dict) < 0) {
     return false;
   }
 
-  PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(
-      &google::protobuf::python::CMessage_Type));
+  PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));
 
-  google::protobuf::python::RepeatedScalarContainer_Type.tp_hash =
+  RepeatedScalarContainer_Type.tp_hash =
       PyObject_HashNotImplemented;
-  if (PyType_Ready(&google::protobuf::python::RepeatedScalarContainer_Type) < 0) {
+  if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
     return false;
   }
 
   PyModule_AddObject(m, "RepeatedScalarContainer",
                      reinterpret_cast<PyObject*>(
-                         &google::protobuf::python::RepeatedScalarContainer_Type));
+                         &RepeatedScalarContainer_Type));
 
-  google::protobuf::python::RepeatedCompositeContainer_Type.tp_hash =
-      PyObject_HashNotImplemented;
-  if (PyType_Ready(&google::protobuf::python::RepeatedCompositeContainer_Type) < 0) {
+  RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented;
+  if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
     return false;
   }
 
   PyModule_AddObject(
       m, "RepeatedCompositeContainer",
       reinterpret_cast<PyObject*>(
-          &google::protobuf::python::RepeatedCompositeContainer_Type));
+          &RepeatedCompositeContainer_Type));
 
-  google::protobuf::python::ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
-  if (PyType_Ready(&google::protobuf::python::ExtensionDict_Type) < 0) {
+  ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
+  if (PyType_Ready(&ExtensionDict_Type) < 0) {
     return false;
   }
 
   PyModule_AddObject(
       m, "ExtensionDict",
-      reinterpret_cast<PyObject*>(&google::protobuf::python::ExtensionDict_Type));
+      reinterpret_cast<PyObject*>(&ExtensionDict_Type));
 
-  if (!google::protobuf::python::InitDescriptor()) {
-    return false;
-  }
+  // This implementation provides full Descriptor types, we advertise it so that
+  // descriptor.py can use them in replacement of the Python classes.
+  PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1);
+
+  PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>(
+      &PyMessageDescriptor_Type));
+  PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>(
+      &PyFieldDescriptor_Type));
+  PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>(
+      &PyEnumDescriptor_Type));
+  PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>(
+      &PyEnumValueDescriptor_Type));
+  PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>(
+      &PyFileDescriptor_Type));
+  PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>(
+      &PyOneofDescriptor_Type));
 
   PyObject* enum_type_wrapper = PyImport_ImportModule(
       "google.protobuf.internal.enum_type_wrapper");
   if (enum_type_wrapper == NULL) {
     return false;
   }
-  google::protobuf::python::EnumTypeWrapper_class =
+  EnumTypeWrapper_class =
       PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper");
   Py_DECREF(enum_type_wrapper);
 
@@ -2481,25 +2509,20 @@
   if (message_module == NULL) {
     return false;
   }
-  google::protobuf::python::EncodeError_class = PyObject_GetAttrString(message_module,
-                                                             "EncodeError");
-  google::protobuf::python::DecodeError_class = PyObject_GetAttrString(message_module,
-                                                             "DecodeError");
+  EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError");
+  DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError");
   Py_DECREF(message_module);
 
   PyObject* pickle_module = PyImport_ImportModule("pickle");
   if (pickle_module == NULL) {
     return false;
   }
-  google::protobuf::python::PickleError_class = PyObject_GetAttrString(pickle_module,
-                                                             "PickleError");
+  PickleError_class = PyObject_GetAttrString(pickle_module, "PickleError");
   Py_DECREF(pickle_module);
 
   // Override {Get,Mutable}CProtoInsidePyProto.
-  google::protobuf::python::GetCProtoInsidePyProtoPtr =
-      google::protobuf::python::GetCProtoInsidePyProtoImpl;
-  google::protobuf::python::MutableCProtoInsidePyProtoPtr =
-      google::protobuf::python::MutableCProtoInsidePyProtoImpl;
+  GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl;
+  MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl;
 
   return true;
 }
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 0fef92a..2f2da79 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -42,7 +42,6 @@
 #endif
 #include <string>
 
-
 namespace google {
 namespace protobuf {
 
@@ -50,12 +49,12 @@
 class Reflection;
 class FieldDescriptor;
 class Descriptor;
+class DynamicMessageFactory;
 
 using internal::shared_ptr;
 
 namespace python {
 
-struct PyDescriptorPool;
 struct ExtensionDict;
 
 typedef struct CMessage {
@@ -84,7 +83,7 @@
   // Used together with the parent's message when making a default message
   // instance mutable.
   // The pointer is owned by the global DescriptorPool.
-  const google::protobuf::FieldDescriptor* parent_field_descriptor;
+  const FieldDescriptor* parent_field_descriptor;
 
   // Pointer to the C++ Message object for this CMessage.  The
   // CMessage does not own this pointer.
@@ -115,27 +114,26 @@
 // Internal function to create a new empty Message Python object, but with empty
 // pointers to the C++ objects.
 // The caller must fill self->message, self->owner and eventually self->parent.
-CMessage* NewEmptyMessage(PyObject* type,
-                          const google::protobuf::Descriptor* descriptor);
+CMessage* NewEmptyMessage(PyObject* type, const Descriptor* descriptor);
 
 // Release a submessage from its proto tree, making it a new top-level messgae.
 // A new message will be created if this is a read-only default instance.
 //
 // Corresponds to reflection api method ReleaseMessage.
-int ReleaseSubMessage(google::protobuf::Message* message,
-                      const google::protobuf::FieldDescriptor* field_descriptor,
+int ReleaseSubMessage(Message* message,
+                      const FieldDescriptor* field_descriptor,
                       CMessage* child_cmessage);
 
 // Retrieves the C++ descriptor of a Python Extension descriptor.
 // On error, return NULL with an exception set.
-const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension);
+const FieldDescriptor* GetExtensionDescriptor(PyObject* extension);
 
 // Initializes a new CMessage instance for a submessage. Only called once per
 // submessage as the result is cached in composite_fields.
 //
 // Corresponds to reflection api method GetMessage.
 PyObject* InternalGetSubMessage(
-    CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor);
+    CMessage* self, const FieldDescriptor* field_descriptor);
 
 // Deletes a range of C++ submessages in a repeated field (following a
 // removal in a RepeatedCompositeContainer).
@@ -146,20 +144,20 @@
 // by slice will be removed from cmessage_list by this function.
 //
 // Corresponds to reflection api method RemoveLast.
-int InternalDeleteRepeatedField(google::protobuf::Message* message,
-                                const google::protobuf::FieldDescriptor* field_descriptor,
+int InternalDeleteRepeatedField(Message* message,
+                                const FieldDescriptor* field_descriptor,
                                 PyObject* slice, PyObject* cmessage_list);
 
 // Sets the specified scalar value to the message.
 int InternalSetScalar(CMessage* self,
-                      const google::protobuf::FieldDescriptor* field_descriptor,
+                      const FieldDescriptor* field_descriptor,
                       PyObject* value);
 
 // Retrieves the specified scalar value from the message.
 //
 // Returns a new python reference.
 PyObject* InternalGetScalar(CMessage* self,
-                            const google::protobuf::FieldDescriptor* field_descriptor);
+                            const FieldDescriptor* field_descriptor);
 
 // Clears the message, removing all contained data. Extension dictionary and
 // submessages are released first if there are remaining external references.
@@ -175,8 +173,7 @@
 //
 // Corresponds to reflection api method ClearField.
 PyObject* ClearFieldByDescriptor(
-    CMessage* self,
-    const google::protobuf::FieldDescriptor* descriptor);
+    CMessage* self, const FieldDescriptor* descriptor);
 
 // Clears the data for the given field name. The message is released if there
 // are any external references.
@@ -189,7 +186,7 @@
 //
 // Corresponds to reflection api method HasField
 PyObject* HasFieldByDescriptor(
-    CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor);
+    CMessage* self, const FieldDescriptor* field_descriptor);
 
 // Checks if the message has the named field.
 //
@@ -220,18 +217,16 @@
 
 int AssureWritable(CMessage* self);
 
+DynamicMessageFactory* GetMessageFactory();
+
 }  // namespace cmessage
 
 
-// Retrieve the global descriptor pool owned by the _message module.
-PyDescriptorPool* GetDescriptorPool();
-
-
 /* Is 64bit */
 #define IS_64BIT (SIZEOF_LONG == 8)
 
 #define FIELD_IS_REPEATED(field_descriptor)                 \
-    ((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED)
+    ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
 
 #define GOOGLE_CHECK_GET_INT32(arg, value, err)                        \
     int32 value;                                            \
@@ -294,18 +289,17 @@
 bool CheckAndGetFloat(PyObject* arg, float* value);
 bool CheckAndGetBool(PyObject* arg, bool* value);
 bool CheckAndSetString(
-    PyObject* arg, google::protobuf::Message* message,
-    const google::protobuf::FieldDescriptor* descriptor,
-    const google::protobuf::Reflection* reflection,
+    PyObject* arg, Message* message,
+    const FieldDescriptor* descriptor,
+    const Reflection* reflection,
     bool append,
     int index);
-PyObject* ToStringObject(
-    const google::protobuf::FieldDescriptor* descriptor, string value);
+PyObject* ToStringObject(const FieldDescriptor* descriptor, string value);
 
 // Check if the passed field descriptor belongs to the given message.
 // If not, return false and set a Python exception (a KeyError)
-bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor,
-                                const google::protobuf::Message* message);
+bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
+                                const Message* message);
 
 extern PyObject* PickleError_class;
 
diff --git a/python/google/protobuf/pyext/message_factory_cpp2_test.py b/python/google/protobuf/pyext/message_factory_cpp2_test.py
deleted file mode 100644
index 32ab4f8..0000000
--- a/python/google/protobuf/pyext/message_factory_cpp2_test.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#! /usr/bin/python
-#
-# 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.
-
-"""Tests for google.protobuf.message_factory."""
-
-import os
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2'
-
-# We must set the implementation version above before the google3 imports.
-# pylint: disable=g-import-not-at-top
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-# Run all tests from the original module by putting them in our namespace.
-# pylint: disable=wildcard-import
-from google.protobuf.internal.message_factory_test import *
-
-
-class ConfirmCppApi2Test(basetest.TestCase):
-
-  def testImplementationSetting(self):
-    self.assertEqual('cpp', api_implementation.Type())
-    self.assertEqual(2, api_implementation.Version())
-
-
-if __name__ == '__main__':
-  basetest.main()
diff --git a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py b/python/google/protobuf/pyext/reflection_cpp2_generated_test.py
deleted file mode 100755
index 552efd4..0000000
--- a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#! /usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# 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.
-
-"""Unittest for reflection.py, which tests the generated C++ implementation."""
-
-__author__ = 'jasonh@google.com (Jason Hsueh)'
-
-import os
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2'
-
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-from google.protobuf.internal import more_extensions_dynamic_pb2
-from google.protobuf.internal import more_extensions_pb2
-from google.protobuf.internal.reflection_test import *
-
-
-class ReflectionCppTest(basetest.TestCase):
-  def testImplementationSetting(self):
-    self.assertEqual('cpp', api_implementation.Type())
-    self.assertEqual(2, api_implementation.Version())
-
-  def testExtensionOfGeneratedTypeInDynamicFile(self):
-    """Tests that a file built dynamically can extend a generated C++ type.
-
-    The C++ implementation uses a DescriptorPool that has the generated
-    DescriptorPool as an underlay. Typically, a type can only find
-    extensions in its own pool. With the python C-extension, the generated C++
-    extendee may be available, but not the extension. This tests that the
-    C-extension implements the correct special handling to make such extensions
-    available.
-    """
-    pb1 = more_extensions_pb2.ExtendedMessage()
-    # Test that basic accessors work.
-    self.assertFalse(
-        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
-    self.assertFalse(
-        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
-    pb1.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension] = 17
-    pb1.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a = 24
-    self.assertTrue(
-        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
-    self.assertTrue(
-        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
-
-    # Now serialize the data and parse to a new message.
-    pb2 = more_extensions_pb2.ExtendedMessage()
-    pb2.MergeFromString(pb1.SerializeToString())
-
-    self.assertTrue(
-        pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
-    self.assertTrue(
-        pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
-    self.assertEqual(
-        17, pb2.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension])
-    self.assertEqual(
-        24,
-        pb2.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a)
-
-
-
-if __name__ == '__main__':
-  basetest.main()
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 36fe86a..0fe98e7 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -56,8 +56,6 @@
 namespace protobuf {
 namespace python {
 
-extern google::protobuf::DynamicMessageFactory* global_message_factory;
-
 namespace repeated_composite_container {
 
 // TODO(tibell): We might also want to check:
@@ -120,9 +118,9 @@
 
   GOOGLE_CHECK_ATTACHED(self);
 
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
-  const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor;
+  Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
+  const FieldDescriptor* descriptor = self->parent_field_descriptor;
   Py_ssize_t left;
   Py_ssize_t right;
 
@@ -199,7 +197,7 @@
 // len()
 
 static Py_ssize_t Length(RepeatedCompositeContainer* self) {
-  google::protobuf::Message* message = self->message;
+  Message* message = self->message;
   if (message != NULL) {
     return message->GetReflection()->FieldSize(*message,
                                                self->parent_field_descriptor);
@@ -221,8 +219,8 @@
   // be removed in such a way so there's no need to worry about that.
   Py_ssize_t message_length = Length(self);
   Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages);
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
   for (Py_ssize_t i = child_length; i < message_length; ++i) {
     const Message& sub_message = reflection->GetRepeatedMessage(
         *(self->message), self->parent_field_descriptor, i);
@@ -233,7 +231,7 @@
       return -1;
     }
     cmsg->owner = self->owner;
-    cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
+    cmsg->message = const_cast<Message*>(&sub_message);
     cmsg->parent = self->parent;
     if (PyList_Append(self->child_messages, py_cmsg) < 0) {
       return -1;
@@ -255,8 +253,8 @@
   }
   if (cmessage::AssureWritable(self->parent) == -1)
     return NULL;
-  google::protobuf::Message* message = self->message;
-  google::protobuf::Message* sub_message =
+  Message* message = self->message;
+  Message* sub_message =
       message->GetReflection()->AddMessage(message,
                                            self->parent_field_descriptor);
   CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init,
@@ -482,9 +480,9 @@
 
   // Finally reverse the result if requested.
   if (reverse) {
-    google::protobuf::Message* message = self->message;
-    const google::protobuf::Reflection* reflection = message->GetReflection();
-    const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor;
+    Message* message = self->message;
+    const Reflection* reflection = message->GetReflection();
+    const FieldDescriptor* descriptor = self->parent_field_descriptor;
 
     // Reverse the Message array.
     for (int i = 0; i < length / 2; ++i)
@@ -554,6 +552,26 @@
   return item;
 }
 
+static PyObject* Pop(RepeatedCompositeContainer* self,
+                     PyObject* args) {
+  Py_ssize_t index = -1;
+  if (!PyArg_ParseTuple(args, "|n", &index)) {
+    return NULL;
+  }
+  PyObject* item = Item(self, index);
+  if (item == NULL) {
+    PyErr_Format(PyExc_IndexError,
+                 "list index (%zd) out of range",
+                 index);
+    return NULL;
+  }
+  ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index));
+  if (AssignSubscript(self, py_index, NULL) < 0) {
+    return NULL;
+  }
+  return item;
+}
+
 // The caller takes ownership of the returned Message.
 Message* ReleaseLast(const FieldDescriptor* field,
                      const Descriptor* type,
@@ -571,7 +589,8 @@
   // the latter points to the default instance via a const_cast<>, so we
   // have to reset it to a new mutable object since we are taking ownership.
   if (released_message == NULL) {
-    const Message* prototype = global_message_factory->GetPrototype(type);
+    const Message* prototype =
+        cmessage::GetMessageFactory()->GetPrototype(type);
     GOOGLE_CHECK_NOTNULL(prototype);
     return prototype->New();
   } else {
@@ -646,7 +665,7 @@
 // The private constructor of RepeatedCompositeContainer objects.
 PyObject *NewContainer(
     CMessage* parent,
-    const google::protobuf::FieldDescriptor* parent_field_descriptor,
+    const FieldDescriptor* parent_field_descriptor,
     PyObject *concrete_class) {
   if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
     return NULL;
@@ -698,6 +717,8 @@
     "Adds an object to the repeated container." },
   { "extend", (PyCFunction) Extend, METH_O,
     "Adds objects to the repeated container." },
+  { "pop", (PyCFunction)Pop, METH_VARARGS,
+    "Removes an object from the repeated container and returns it." },
   { "remove", (PyCFunction) Remove, METH_O,
     "Removes an object from the repeated container." },
   { "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS,
@@ -711,9 +732,10 @@
 
 PyTypeObject RepeatedCompositeContainer_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  "google.protobuf.internal."
-  "cpp._message.RepeatedCompositeContainer",  // tp_name
-  sizeof(RepeatedCompositeContainer),     // tp_basicsize
+  // Keep the fully qualified _message symbol in a line for opensource.
+  "google.protobuf.pyext._message."
+  "RepeatedCompositeContainer",        // tp_name
+  sizeof(RepeatedCompositeContainer),  // tp_basicsize
   0,                                   //  tp_itemsize
   (destructor)repeated_composite_container::Dealloc,  //  tp_dealloc
   0,                                   //  tp_print
diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h
index 0969af0..ce7cee0 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.h
+++ b/python/google/protobuf/pyext/repeated_composite_container.h
@@ -43,7 +43,6 @@
 #include <string>
 #include <vector>
 
-
 namespace google {
 namespace protobuf {
 
@@ -82,7 +81,7 @@
 
   // A descriptor used to modify the underlying 'message'.
   // The pointer is owned by the global DescriptorPool.
-  const google::protobuf::FieldDescriptor* parent_field_descriptor;
+  const FieldDescriptor* parent_field_descriptor;
 
   // Pointer to the C++ Message that contains this container.  The
   // RepeatedCompositeContainer does not own this pointer.
@@ -106,7 +105,7 @@
 // field descriptor.
 PyObject *NewContainer(
     CMessage* parent,
-    const google::protobuf::FieldDescriptor* parent_field_descriptor,
+    const FieldDescriptor* parent_field_descriptor,
     PyObject *concrete_class);
 
 // Returns the number of items in this repeated composite container.
@@ -150,8 +149,7 @@
 // Releases the messages in the container to the given message.
 //
 // Returns 0 on success, -1 on failure.
-int ReleaseToMessage(RepeatedCompositeContainer* self,
-                     google::protobuf::Message* new_message);
+int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message);
 
 // Releases the messages in the container to a new message.
 //
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 49d23fd..110a4c8 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -60,8 +60,6 @@
 namespace protobuf {
 namespace python {
 
-extern google::protobuf::DynamicMessageFactory* global_message_factory;
-
 namespace repeated_scalar_container {
 
 static int InternalAssignRepeatedField(
@@ -78,7 +76,7 @@
 }
 
 static Py_ssize_t Len(RepeatedScalarContainer* self) {
-  google::protobuf::Message* message = self->message;
+  Message* message = self->message;
   return message->GetReflection()->FieldSize(*message,
                                              self->parent_field_descriptor);
 }
@@ -87,11 +85,10 @@
                       Py_ssize_t index,
                       PyObject* arg) {
   cmessage::AssureWritable(self->parent);
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      self->parent_field_descriptor;
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
 
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  const Reflection* reflection = message->GetReflection();
   int field_size = reflection->FieldSize(*message, field_descriptor);
   if (index < 0) {
     index = field_size + index;
@@ -115,64 +112,68 @@
   }
 
   switch (field_descriptor->cpp_type()) {
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+    case FieldDescriptor::CPPTYPE_INT32: {
       GOOGLE_CHECK_GET_INT32(arg, value, -1);
       reflection->SetRepeatedInt32(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+    case FieldDescriptor::CPPTYPE_INT64: {
       GOOGLE_CHECK_GET_INT64(arg, value, -1);
       reflection->SetRepeatedInt64(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+    case FieldDescriptor::CPPTYPE_UINT32: {
       GOOGLE_CHECK_GET_UINT32(arg, value, -1);
       reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+    case FieldDescriptor::CPPTYPE_UINT64: {
       GOOGLE_CHECK_GET_UINT64(arg, value, -1);
       reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+    case FieldDescriptor::CPPTYPE_FLOAT: {
       GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
       reflection->SetRepeatedFloat(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
       GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
       reflection->SetRepeatedDouble(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+    case FieldDescriptor::CPPTYPE_BOOL: {
       GOOGLE_CHECK_GET_BOOL(arg, value, -1);
       reflection->SetRepeatedBool(message, field_descriptor, index, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+    case FieldDescriptor::CPPTYPE_STRING: {
       if (!CheckAndSetString(
           arg, message, field_descriptor, reflection, false, index)) {
         return -1;
       }
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+    case FieldDescriptor::CPPTYPE_ENUM: {
       GOOGLE_CHECK_GET_INT32(arg, value, -1);
-      const google::protobuf::EnumDescriptor* enum_descriptor =
-          field_descriptor->enum_type();
-      const google::protobuf::EnumValueDescriptor* enum_value =
-          enum_descriptor->FindValueByNumber(value);
-      if (enum_value != NULL) {
-        reflection->SetRepeatedEnum(message, field_descriptor, index,
-                                    enum_value);
+      if (reflection->SupportsUnknownEnumValues()) {
+        reflection->SetRepeatedEnumValue(message, field_descriptor, index,
+                                         value);
       } else {
-        ScopedPyObjectPtr s(PyObject_Str(arg));
-        if (s != NULL) {
-          PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
-                       PyString_AsString(s));
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          reflection->SetRepeatedEnum(message, field_descriptor, index,
+                                      enum_value);
+        } else {
+          ScopedPyObjectPtr s(PyObject_Str(arg));
+          if (s != NULL) {
+            PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+                         PyString_AsString(s));
+          }
+          return -1;
         }
-        return -1;
       }
       break;
     }
@@ -186,10 +187,9 @@
 }
 
 static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      self->parent_field_descriptor;
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
+  const Reflection* reflection = message->GetReflection();
 
   int field_size = reflection->FieldSize(*message, field_descriptor);
   if (index < 0) {
@@ -197,80 +197,80 @@
   }
   if (index < 0 || index >= field_size) {
     PyErr_Format(PyExc_IndexError,
-                 "list assignment index (%d) out of range",
-                 static_cast<int>(index));
+                 "list index (%zd) out of range",
+                 index);
     return NULL;
   }
 
   PyObject* result = NULL;
   switch (field_descriptor->cpp_type()) {
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+    case FieldDescriptor::CPPTYPE_INT32: {
       int32 value = reflection->GetRepeatedInt32(
           *message, field_descriptor, index);
       result = PyInt_FromLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+    case FieldDescriptor::CPPTYPE_INT64: {
       int64 value = reflection->GetRepeatedInt64(
           *message, field_descriptor, index);
       result = PyLong_FromLongLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+    case FieldDescriptor::CPPTYPE_UINT32: {
       uint32 value = reflection->GetRepeatedUInt32(
           *message, field_descriptor, index);
       result = PyLong_FromLongLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+    case FieldDescriptor::CPPTYPE_UINT64: {
       uint64 value = reflection->GetRepeatedUInt64(
           *message, field_descriptor, index);
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+    case FieldDescriptor::CPPTYPE_FLOAT: {
       float value = reflection->GetRepeatedFloat(
           *message, field_descriptor, index);
       result = PyFloat_FromDouble(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = reflection->GetRepeatedDouble(
           *message, field_descriptor, index);
       result = PyFloat_FromDouble(value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+    case FieldDescriptor::CPPTYPE_BOOL: {
       bool value = reflection->GetRepeatedBool(
           *message, field_descriptor, index);
       result = PyBool_FromLong(value ? 1 : 0);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
-      const google::protobuf::EnumValueDescriptor* enum_value =
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      const EnumValueDescriptor* enum_value =
           message->GetReflection()->GetRepeatedEnum(
               *message, field_descriptor, index);
       result = PyInt_FromLong(enum_value->number());
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+    case FieldDescriptor::CPPTYPE_STRING: {
       string value = reflection->GetRepeatedString(
           *message, field_descriptor, index);
       result = ToStringObject(field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+    case FieldDescriptor::CPPTYPE_MESSAGE: {
       PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast<PyObject*>(
           &CMessage_Type), NULL);
       if (py_cmsg == NULL) {
         return NULL;
       }
       CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
-      const google::protobuf::Message& msg = reflection->GetRepeatedMessage(
+      const Message& msg = reflection->GetRepeatedMessage(
           *message, field_descriptor, index);
       cmsg->owner = self->owner;
       cmsg->parent = self->parent;
-      cmsg->message = const_cast<google::protobuf::Message*>(&msg);
+      cmsg->message = const_cast<Message*>(&msg);
       cmsg->read_only = false;
       result = reinterpret_cast<PyObject*>(py_cmsg);
       break;
@@ -351,69 +351,71 @@
 
 PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
   cmessage::AssureWritable(self->parent);
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::FieldDescriptor* field_descriptor =
-      self->parent_field_descriptor;
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
 
-  const google::protobuf::Reflection* reflection = message->GetReflection();
+  const Reflection* reflection = message->GetReflection();
   switch (field_descriptor->cpp_type()) {
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+    case FieldDescriptor::CPPTYPE_INT32: {
       GOOGLE_CHECK_GET_INT32(item, value, NULL);
       reflection->AddInt32(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+    case FieldDescriptor::CPPTYPE_INT64: {
       GOOGLE_CHECK_GET_INT64(item, value, NULL);
       reflection->AddInt64(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+    case FieldDescriptor::CPPTYPE_UINT32: {
       GOOGLE_CHECK_GET_UINT32(item, value, NULL);
       reflection->AddUInt32(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+    case FieldDescriptor::CPPTYPE_UINT64: {
       GOOGLE_CHECK_GET_UINT64(item, value, NULL);
       reflection->AddUInt64(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+    case FieldDescriptor::CPPTYPE_FLOAT: {
       GOOGLE_CHECK_GET_FLOAT(item, value, NULL);
       reflection->AddFloat(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
       GOOGLE_CHECK_GET_DOUBLE(item, value, NULL);
       reflection->AddDouble(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+    case FieldDescriptor::CPPTYPE_BOOL: {
       GOOGLE_CHECK_GET_BOOL(item, value, NULL);
       reflection->AddBool(message, field_descriptor, value);
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+    case FieldDescriptor::CPPTYPE_STRING: {
       if (!CheckAndSetString(
           item, message, field_descriptor, reflection, true, -1)) {
         return NULL;
       }
       break;
     }
-    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+    case FieldDescriptor::CPPTYPE_ENUM: {
       GOOGLE_CHECK_GET_INT32(item, value, NULL);
-      const google::protobuf::EnumDescriptor* enum_descriptor =
-          field_descriptor->enum_type();
-      const google::protobuf::EnumValueDescriptor* enum_value =
-          enum_descriptor->FindValueByNumber(value);
-      if (enum_value != NULL) {
-        reflection->AddEnum(message, field_descriptor, enum_value);
+      if (reflection->SupportsUnknownEnumValues()) {
+        reflection->AddEnumValue(message, field_descriptor, value);
       } else {
-        ScopedPyObjectPtr s(PyObject_Str(item));
-        if (s != NULL) {
-          PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
-                       PyString_AsString(s));
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          reflection->AddEnum(message, field_descriptor, enum_value);
+        } else {
+          ScopedPyObjectPtr s(PyObject_Str(item));
+          if (s != NULL) {
+            PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+                         PyString_AsString(s));
+          }
+          return NULL;
         }
-        return NULL;
       }
       break;
     }
@@ -438,8 +440,8 @@
   bool create_list = false;
 
   cmessage::AssureWritable(self->parent);
-  google::protobuf::Message* message = self->message;
-  const google::protobuf::FieldDescriptor* field_descriptor =
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor =
       self->parent_field_descriptor;
 
 #if PY_MAJOR_VERSION < 3
@@ -450,7 +452,7 @@
   if (PyLong_Check(slice)) {
     from = to = PyLong_AsLong(slice);
   } else if (PySlice_Check(slice)) {
-    const google::protobuf::Reflection* reflection = message->GetReflection();
+    const Reflection* reflection = message->GetReflection();
     length = reflection->FieldSize(*message, field_descriptor);
 #if PY_MAJOR_VERSION >= 3
     if (PySlice_GetIndicesEx(slice,
@@ -492,9 +494,15 @@
 
 PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
   cmessage::AssureWritable(self->parent);
-  if (PyObject_Not(value)) {
+
+  // TODO(ptucker): Deprecate this behavior. b/18413862
+  if (value == Py_None) {
     Py_RETURN_NONE;
   }
+  if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) {
+    Py_RETURN_NONE;
+  }
+
   ScopedPyObjectPtr iter(PyObject_GetIter(value));
   if (iter == NULL) {
     PyErr_SetString(PyExc_TypeError, "Value must be iterable");
@@ -627,9 +635,28 @@
   Py_RETURN_NONE;
 }
 
+static PyObject* Pop(RepeatedScalarContainer* self,
+                     PyObject* args) {
+  Py_ssize_t index = -1;
+  if (!PyArg_ParseTuple(args, "|n", &index)) {
+    return NULL;
+  }
+  PyObject* item = Item(self, index);
+  if (item == NULL) {
+    PyErr_Format(PyExc_IndexError,
+                 "list index (%zd) out of range",
+                 index);
+    return NULL;
+  }
+  if (AssignItem(self, index, NULL) < 0) {
+    return NULL;
+  }
+  return item;
+}
+
 // The private constructor of RepeatedScalarContainer objects.
 PyObject *NewContainer(
-    CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
+    CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
   if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
     return NULL;
   }
@@ -663,7 +690,7 @@
   if (values == NULL) {
     return -1;
   }
-  google::protobuf::Message* new_message = global_message_factory->GetPrototype(
+  Message* new_message = cmessage::GetMessageFactory()->GetPrototype(
       from->message->GetDescriptor())->New();
   to->parent = NULL;
   to->parent_field_descriptor = from->parent_field_descriptor;
@@ -729,6 +756,8 @@
     "Appends objects to the repeated container." },
   { "insert", (PyCFunction)Insert, METH_VARARGS,
     "Appends objects to the repeated container." },
+  { "pop", (PyCFunction)Pop, METH_VARARGS,
+    "Removes an object from the repeated container and returns it." },
   { "remove", (PyCFunction)Remove, METH_O,
     "Removes an object from the repeated container." },
   { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
@@ -740,8 +769,9 @@
 
 PyTypeObject RepeatedScalarContainer_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  "google.protobuf.internal."
-  "cpp._message.RepeatedScalarContainer",  // tp_name
+  // Keep the fully qualified _message symbol in a line for opensource.
+  "google.protobuf.pyext._message."
+  "RepeatedScalarContainer",           // tp_name
   sizeof(RepeatedScalarContainer),     // tp_basicsize
   0,                                   //  tp_itemsize
   (destructor)repeated_scalar_container::Dealloc,  //  tp_dealloc
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h
index 513bfe4..5dfa21e 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.h
+++ b/python/google/protobuf/pyext/repeated_scalar_container.h
@@ -77,7 +77,7 @@
   // field.  Used together with the parent's message when making a
   // default message instance mutable.
   // The pointer is owned by the global DescriptorPool.
-  const google::protobuf::FieldDescriptor* parent_field_descriptor;
+  const FieldDescriptor* parent_field_descriptor;
 } RepeatedScalarContainer;
 
 extern PyTypeObject RepeatedScalarContainer_Type;
@@ -87,7 +87,7 @@
 // Builds a RepeatedScalarContainer object, from a parent message and a
 // field descriptor.
 extern PyObject *NewContainer(
-    CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor);
+    CMessage* parent, const FieldDescriptor* parent_field_descriptor);
 
 // Appends the scalar 'item' to the end of the container 'self'.
 //
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 1fc704a..55e653a 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -56,18 +56,12 @@
 
 
 if api_implementation.Type() == 'cpp':
-  if api_implementation.Version() == 2:
-    from google.protobuf.pyext import cpp_message
-    _NewMessage = cpp_message.NewMessage
-    _InitMessage = cpp_message.InitMessage
-  else:
-    from google.protobuf.internal import cpp_message
-    _NewMessage = cpp_message.NewMessage
-    _InitMessage = cpp_message.InitMessage
+  from google.protobuf.pyext import cpp_message as message_impl
 else:
-  from google.protobuf.internal import python_message
-  _NewMessage = python_message.NewMessage
-  _InitMessage = python_message.InitMessage
+  from google.protobuf.internal import python_message as message_impl
+
+_NewMessage = message_impl.NewMessage
+_InitMessage = message_impl.InitMessage
 
 
 class GeneratedProtocolMessageType(type):
@@ -127,7 +121,6 @@
     superclass = super(GeneratedProtocolMessageType, cls)
 
     new_class = superclass.__new__(cls, name, bases, dictionary)
-    setattr(descriptor, '_concrete_class', new_class)
     return new_class
 
   def __init__(cls, name, bases, dictionary):
@@ -151,6 +144,7 @@
     _InitMessage(descriptor, cls)
     superclass = super(GeneratedProtocolMessageType, cls)
     superclass.__init__(name, bases, dictionary)
+    setattr(descriptor, '_concrete_class', cls)
 
 
 def ParseMessage(descriptor, byte_str):
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index fb54c50..a47ce3e 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -319,6 +319,11 @@
     ParseError: In case of ASCII parsing problems.
   """
   message_descriptor = message.DESCRIPTOR
+  if (hasattr(message_descriptor, 'syntax') and
+      message_descriptor.syntax == 'proto3'):
+    # Proto3 doesn't represent presence so we can't test if multiple
+    # scalars have occurred.  We have to allow them.
+    allow_multiple_scalars = True
   if tokenizer.TryConsume('['):
     name = [tokenizer.ConsumeIdentifier()]
     while tokenizer.TryConsume('.'):
diff --git a/python/setup.py b/python/setup.py
index cfe25cc..c18818e 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -44,6 +44,18 @@
 else:
   protoc = find_executable("protoc")
 
+def GetVersion():
+  """Gets the version from google/protobuf/__init__.py
+
+  Do not import google.protobuf.__init__ directly, because an installed protobuf
+  library may be loaded instead.
+
+  """
+  with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
+    exec(version_file.read())
+    return __version__
+
+
 def generate_proto(source):
   """Invokes the Protocol Compiler to generate a _pb2.py from the given
   .proto file.  Does nothing if the output already exists and is newer than
@@ -77,6 +89,7 @@
   generate_proto("../src/google/protobuf/unittest_import_public.proto")
   generate_proto("../src/google/protobuf/unittest_mset.proto")
   generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
+  generate_proto("../src/google/protobuf/unittest_proto3_arena.proto")
   generate_proto("google/protobuf/internal/descriptor_pool_test1.proto")
   generate_proto("google/protobuf/internal/descriptor_pool_test2.proto")
   generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
@@ -90,23 +103,6 @@
   generate_proto("google/protobuf/internal/import_test_package/outer.proto")
   generate_proto("google/protobuf/pyext/python.proto")
 
-def MakeTestSuite():
-  # Test C++ implementation
-  import unittest
-  import google.protobuf.pyext.descriptor_cpp2_test as descriptor_cpp2_test
-  import google.protobuf.pyext.message_factory_cpp2_test \
-      as message_factory_cpp2_test
-  import google.protobuf.pyext.reflection_cpp2_generated_test \
-      as reflection_cpp2_generated_test
-
-  loader = unittest.defaultTestLoader
-  suite = unittest.TestSuite()
-  for test in [  descriptor_cpp2_test,
-                 message_factory_cpp2_test,
-                 reflection_cpp2_generated_test]:
-    suite.addTest(loader.loadTestsFromModule(test))
-  return suite
-
 class clean(_clean):
   def run(self):
     # Delete generated files in the code tree.
@@ -152,6 +148,8 @@
     ext_module_list.append(Extension(
         "google.protobuf.pyext._message",
         [ "google/protobuf/pyext/descriptor.cc",
+          "google/protobuf/pyext/descriptor_containers.cc",
+          "google/protobuf/pyext/descriptor_pool.cc",
           "google/protobuf/pyext/message.cc",
           "google/protobuf/pyext/extension_dict.cc",
           "google/protobuf/pyext/repeated_scalar_container.cc",
@@ -161,12 +159,12 @@
         libraries = [ "protobuf" ],
         library_dirs = [ '../src/.libs' ],
         ))
+    os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
 
   setup(name = 'protobuf',
-        version = '3.0.0-pre',
+        version = GetVersion(),
         packages = [ 'google' ],
         namespace_packages = [ 'google' ],
-        test_suite = 'setup.MakeTestSuite',
         google_test_dir = "google/protobuf/internal",
         # Must list modules explicitly so that we don't install tests.
         py_modules = [
diff --git a/ruby/README.md b/ruby/README.md
index c966a10..8331d28 100644
--- a/ruby/README.md
+++ b/ruby/README.md
@@ -7,8 +7,51 @@
 build process in this directory only installs the extension; you need to
 install protoc as well to have Ruby code generation functionality.
 
-Installation
-------------
+Installation from Gem
+---------------------
+
+When we release a version of Protocol Buffers, we will upload a Gem to
+[RubyGems](https://www.rubygems.org/). To use this pre-packaged gem, simply
+install it as you would any other gem:
+
+    $ gem install [--prerelease] google-protobuf
+
+The `--pre` flag is necessary if we have not yet made a non-alpha/beta release
+of the Ruby extension; it allows `gem` to consider these "pre-release"
+alpha/beta versions.
+
+Once the gem is installed, you may or may not need `protoc`. If you write your
+message type descriptions directly in the Ruby DSL, you do not need it.
+However, if you wish to generate the Ruby DSL from a `.proto` file, you will
+also want to install Protocol Buffers itself, as described in this repository's
+main `README` file. The version of `protoc` included in the latest release
+supports the `--ruby_out` option to generate Ruby code.
+
+A simple example of using the Ruby extension follows. More extensive
+documentation may be found in the RubyDoc comments (`call-seq` tags) in the
+source, and we plan to release separate, more detailed, documentation at a
+later date.
+
+    require 'google/protobuf'
+
+    # generated from my_proto_types.proto with protoc:
+    #  $ protoc --ruby_out=. my_proto_types.proto
+    require 'my_proto_types'
+
+    mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"])
+    mymessage.field1 = 43
+    mymessage.field2.push("d")
+    mymessage.field3 = SubMessage.new(:foo => 100)
+
+    encoded_data = MyTestMessage.encode(mymessage)
+    decoded = MyTestMessage.decode(encoded_data)
+    assert decoded == mymessage
+
+    puts "JSON:"
+    puts MyTestMessage.encode_json(mymessage)
+
+Installation from Source (Building Gem)
+---------------------------------------
 
 To build this Ruby extension, you will need:
 
@@ -16,15 +59,8 @@
 * Bundler
 * Ruby development headers
 * a C compiler
-* the upb submodule
 
-First, ensure that upb/ is checked out:
-
-    $ cd ..   # top level protobuf directory
-    $ git submodule init
-    $ git submodule update
-
-Then install the required Ruby gems:
+First, install the required Ruby gems:
 
     $ sudo gem install bundler rake rake-compiler rspec rubygems-tasks
 
@@ -32,3 +68,31 @@
 
     $ rake gem
     $ gem install pkg/protobuf-$VERSION.gem
+
+This gem includes the upb parsing and serialization library as a single-file
+amalgamation. It is up-to-date with upb git commit
+`535bc2fe2f2b467f59347ffc9449e11e47791257`.
+
+Version Number Scheme
+---------------------
+
+We are using a version number scheme that is a hybrid of Protocol Buffers'
+overall version number and some Ruby-specific rules. Gem does not allow
+re-uploads of a gem with the same version number, so we add a sequence number
+("upload version") to the version. We also format alphabetical tags (alpha,
+pre, ...) slightly differently, and we avoid hyphens. In more detail:
+
+* First, we determine the prefix: a Protocol Buffers version "3.0.0-alpha-2"
+  becomes "3.0.0.alpha.2". When we release 3.0.0, this prefix will be simply
+  "3.0.0".
+* We then append the upload version: "3.0.0.alpha.2.0" or "3.0.0.0". If we need
+  to upload a new version of the gem to fix an issue, the version becomes
+  "3.0.0.alpha.2.1" or "3.0.0.1".
+* If we are working on a prerelease version, we append a prerelease tag:
+  "3.0.0.alpha.3.0.pre". The prerelease tag comes at the end so that when
+  version numbers are sorted, any prerelease builds are ordered between the
+  prior version and current version.
+
+These rules are designed to work with the sorting rules for
+[Gem::Version](http://ruby-doc.org/stdlib-2.0/libdoc/rubygems/rdoc/Gem/Version.html):
+release numbers should sort in actual release order.
diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c
index a18aaac..b39c27f 100644
--- a/ruby/ext/google/protobuf_c/defs.c
+++ b/ruby/ext/google/protobuf_c/defs.c
@@ -58,11 +58,15 @@
 }
 
 static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) {
-  return (upb_msgdef*)check_notfrozen((const upb_def*)def);
+  return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def*)def));
 }
 
 static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) {
-  return (upb_fielddef*)check_notfrozen((const upb_def*)def);
+  return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def*)def));
+}
+
+static upb_oneofdef* check_oneof_notfrozen(const upb_oneofdef* def) {
+  return (upb_oneofdef*)check_notfrozen((const upb_def*)def);
 }
 
 static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
@@ -282,6 +286,9 @@
   rb_define_method(klass, "each", Descriptor_each, 0);
   rb_define_method(klass, "lookup", Descriptor_lookup, 1);
   rb_define_method(klass, "add_field", Descriptor_add_field, 1);
+  rb_define_method(klass, "add_oneof", Descriptor_add_oneof, 1);
+  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
+  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
   rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
   rb_define_method(klass, "name", Descriptor_name, 0);
   rb_define_method(klass, "name=", Descriptor_name_set, 1);
@@ -328,10 +335,10 @@
 VALUE Descriptor_each(VALUE _self) {
   DEFINE_SELF(Descriptor, self, _self);
 
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, self->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, self->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
     VALUE obj = get_def_obj(field);
     rb_yield(obj);
@@ -360,7 +367,7 @@
  * call-seq:
  *     Descriptor.add_field(field) => nil
  *
- * Adds the given FieldDescriptor to this message type. The descriptor must not
+ * Adds the given FieldDescriptor to this message type. This descriptor must not
  * have been added to a pool yet. Raises an exception if a field with the same
  * name or number already exists. Sub-type references (e.g. for fields of type
  * message) are not resolved at this point.
@@ -379,6 +386,67 @@
 
 /*
  * call-seq:
+ *     Descriptor.add_oneof(oneof) => nil
+ *
+ * Adds the given OneofDescriptor to this message type. This descriptor must not
+ * have been added to a pool yet. Raises an exception if a oneof with the same
+ * name already exists, or if any of the oneof's fields' names or numbers
+ * conflict with an existing field in this message type. All fields in the oneof
+ * are added to the message descriptor. Sub-type references (e.g. for fields of
+ * type message) are not resolved at this point.
+ */
+VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) {
+  DEFINE_SELF(Descriptor, self, _self);
+  upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
+  OneofDescriptor* def = ruby_to_OneofDescriptor(obj);
+  upb_oneofdef* mut_oneof_def = check_oneof_notfrozen(def->oneofdef);
+  CHECK_UPB(
+      upb_msgdef_addoneof(mut_def, mut_oneof_def, NULL, &status),
+      "Adding oneof to Descriptor failed");
+  add_def_obj(def->oneofdef, obj);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each_oneof(&block) => nil
+ *
+ * Invokes the given block for each oneof in this message type, passing the
+ * corresponding OneofDescriptor.
+ */
+VALUE Descriptor_each_oneof(VALUE _self) {
+  DEFINE_SELF(Descriptor, self, _self);
+
+  upb_msg_oneof_iter it;
+  for (upb_msg_oneof_begin(&it, self->msgdef);
+       !upb_msg_oneof_done(&it);
+       upb_msg_oneof_next(&it)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
+    VALUE obj = get_def_obj(oneof);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup_oneof(name) => OneofDescriptor
+ *
+ * Returns the oneof descriptor for the oneof with the given name, if present,
+ * or nil if none.
+ */
+VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
+  DEFINE_SELF(Descriptor, self, _self);
+  const char* s = get_str(name);
+  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
+  if (oneof == NULL) {
+    return Qnil;
+  }
+  return get_def_obj(oneof);
+}
+
+/*
+ * call-seq:
  *     Descriptor.msgclass => message_klass
  *
  * Returns the Ruby class created for this message type. Valid only once the
@@ -744,6 +812,120 @@
 }
 
 // -----------------------------------------------------------------------------
+// OneofDescriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
+
+void OneofDescriptor_mark(void* _self) {
+}
+
+void OneofDescriptor_free(void* _self) {
+  OneofDescriptor* self = _self;
+  upb_oneofdef_unref(self->oneofdef, &self->oneofdef);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.new => oneof_descriptor
+ *
+ * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
+ * to being added to a message descriptor which is subsequently added to a pool.
+ */
+VALUE OneofDescriptor_alloc(VALUE klass) {
+  OneofDescriptor* self = ALLOC(OneofDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
+  self->oneofdef = upb_oneofdef_new(&self->oneofdef);
+  return ret;
+}
+
+void OneofDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, OneofDescriptor_alloc);
+  rb_define_method(klass, "name", OneofDescriptor_name, 0);
+  rb_define_method(klass, "name=", OneofDescriptor_name_set, 1);
+  rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1);
+  rb_define_method(klass, "each", OneofDescriptor_each, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  cOneofDescriptor = klass;
+  rb_gc_register_address(&cOneofDescriptor);
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.name => name
+ *
+ * Returns the name of this oneof.
+ */
+VALUE OneofDescriptor_name(VALUE _self) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.name = name
+ *
+ * Sets a new name for this oneof. The oneof must not have been added to a
+ * message descriptor yet.
+ */
+VALUE OneofDescriptor_name_set(VALUE _self, VALUE value) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
+  const char* str = get_str(value);
+  CHECK_UPB(upb_oneofdef_setname(mut_def, str, &status),
+            "Error setting oneof name");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.add_field(field) => nil
+ *
+ * Adds a field to this oneof. The field may have been added to this oneof in
+ * the past, or the message to which this oneof belongs (if any), but may not
+ * have already been added to any other oneof or message. Otherwise, an
+ * exception is raised.
+ *
+ * All fields added to the oneof via this method will be automatically added to
+ * the message to which this oneof belongs, if it belongs to one currently, or
+ * else will be added to any message to which the oneof is later added at the
+ * time that it is added.
+ */
+VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
+  FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
+  upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
+  CHECK_UPB(
+      upb_oneofdef_addfield(mut_def, mut_field_def, NULL, &status),
+      "Adding field to OneofDescriptor failed");
+  add_def_obj(def->fielddef, obj);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.each(&block) => nil
+ *
+ * Iterates through fields in this oneof, yielding to the block on each one.
+ */
+VALUE OneofDescriptor_each(VALUE _self, VALUE field) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  upb_oneof_iter it;
+  for (upb_oneof_begin(&it, self->oneofdef);
+       !upb_oneof_done(&it);
+       upb_oneof_next(&it)) {
+    const upb_fielddef* f = upb_oneof_iter_field(&it);
+    VALUE obj = get_def_obj(f);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+// -----------------------------------------------------------------------------
 // EnumDescriptor.
 // -----------------------------------------------------------------------------
 
@@ -952,6 +1134,7 @@
   rb_define_method(klass, "required", MessageBuilderContext_required, -1);
   rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
   rb_define_method(klass, "map", MessageBuilderContext_map, -1);
+  rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
   cMessageBuilderContext = klass;
   rb_gc_register_address(&cMessageBuilderContext);
 }
@@ -1165,6 +1348,110 @@
   return Qnil;
 }
 
+/*
+ * call-seq:
+ *     MessageBuilderContext.oneof(name, &block) => nil
+ *
+ * Creates a new OneofDescriptor with the given name, creates a
+ * OneofBuilderContext attached to that OneofDescriptor, evaluates the given
+ * block in the context of that OneofBuilderContext with #instance_eval, and
+ * then adds the oneof to the message.
+ *
+ * This is the recommended, idiomatic way to build oneof definitions.
+ */
+VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  VALUE oneofdef = rb_class_new_instance(0, NULL, cOneofDescriptor);
+  VALUE args[2] = { oneofdef, self->builder };
+  VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
+  VALUE block = rb_block_proc();
+  VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
+  rb_funcall(oneofdef, rb_intern("name="), 1, name_str);
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  Descriptor_add_oneof(self->descriptor, oneofdef);
+
+  return Qnil;
+}
+
+// -----------------------------------------------------------------------------
+// OneofBuilderContext.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(OneofBuilderContext,
+    "Google::Protobuf::Internal::OneofBuilderContext");
+
+void OneofBuilderContext_mark(void* _self) {
+  OneofBuilderContext* self = _self;
+  rb_gc_mark(self->descriptor);
+  rb_gc_mark(self->builder);
+}
+
+void OneofBuilderContext_free(void* _self) {
+  OneofBuilderContext* self = _self;
+  xfree(self);
+}
+
+VALUE OneofBuilderContext_alloc(VALUE klass) {
+  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(
+      klass, &_OneofBuilderContext_type, self);
+  self->descriptor = Qnil;
+  self->builder = Qnil;
+  return ret;
+}
+
+void OneofBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, OneofBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   OneofBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
+  cOneofBuilderContext = klass;
+  rb_gc_register_address(&cOneofBuilderContext);
+}
+
+/*
+ * call-seq:
+ *     OneofBuilderContext.new(desc, builder) => context
+ *
+ * Create a new oneof builder context around the given oneof descriptor and
+ * builder context. This class is intended to serve as a DSL context to be used
+ * with #instance_eval.
+ */
+VALUE OneofBuilderContext_initialize(VALUE _self,
+                                     VALUE oneofdef,
+                                     VALUE builder) {
+  DEFINE_SELF(OneofBuilderContext, self, _self);
+  self->descriptor = oneofdef;
+  self->builder = builder;
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofBuilderContext.optional(name, type, number, type_class = nil)
+ *
+ * Defines a new optional field in this oneof with the given type, tag number,
+ * and type class (for message and enum fields). The type must be a Ruby symbol
+ * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
+ * if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
+  DEFINE_SELF(OneofBuilderContext, self, _self);
+
+  if (argc < 3) {
+    rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+  }
+  VALUE name = argv[0];
+  VALUE type = argv[1];
+  VALUE number = argv[2];
+  VALUE type_class = (argc > 3) ? argv[3] : Qnil;
+
+  return msgdef_add_field(self->descriptor, "optional",
+                          name, type, number, type_class);
+}
+
 // -----------------------------------------------------------------------------
 // EnumBuilderContext.
 // -----------------------------------------------------------------------------
@@ -1322,8 +1609,10 @@
 
 static void validate_msgdef(const upb_msgdef* msgdef) {
   // Verify that no required fields exist. proto3 does not support these.
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
     if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
       rb_raise(rb_eTypeError, "Required fields are unsupported in proto3.");
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
index e5e1514..5730504 100644
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ b/ruby/ext/google/protobuf_c/encode_decode.c
@@ -59,6 +59,36 @@
   return hd;
 }
 
+typedef struct {
+  size_t ofs;              // union data slot
+  size_t case_ofs;         // oneof_case field
+  uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
+  const upb_msgdef *md;    // msgdef, for oneof submessage handler
+} oneof_handlerdata_t;
+
+static const void *newoneofhandlerdata(upb_handlers *h,
+                                       uint32_t ofs,
+                                       uint32_t case_ofs,
+                                       const upb_fielddef *f) {
+  oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
+  hd->ofs = ofs;
+  hd->case_ofs = case_ofs;
+  // We reuse the field tag number as a oneof union discriminant tag. Note that
+  // we don't expose these numbers to the user, so the only requirement is that
+  // we have some unique ID for each union case/possibility. The field tag
+  // numbers are already present and are easy to use so there's no reason to
+  // create a separate ID space. In addition, using the field tag number here
+  // lets us easily look up the field in the oneof accessor.
+  hd->oneof_case_num = upb_fielddef_number(f);
+  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
+    hd->md = upb_fielddef_msgsubdef(f);
+  } else {
+    hd->md = NULL;
+  }
+  upb_handlers_addcleanup(h, hd, free);
+  return hd;
+}
+
 // A handler that starts a repeated field.  Gets the Repeated*Field instance for
 // this field (such an instance always exists even in an empty message).
 static void *startseq_handler(void* closure, const void* hd) {
@@ -67,8 +97,7 @@
   return (void*)DEREF(msg, *ofs, VALUE);
 }
 
-// Handlers that append primitive values to a repeated field (a regular Ruby
-// array for now).
+// Handlers that append primitive values to a repeated field.
 #define DEFINE_APPEND_HANDLER(type, ctype)                 \
   static bool append##type##_handler(void *closure, const void *hd, \
                                      ctype val) {                   \
@@ -85,7 +114,7 @@
 DEFINE_APPEND_HANDLER(uint64, uint64_t)
 DEFINE_APPEND_HANDLER(double, double)
 
-// Appends a string to a repeated field (a regular Ruby array for now).
+// Appends a string to a repeated field.
 static void* appendstr_handler(void *closure,
                                const void *hd,
                                size_t size_hint) {
@@ -96,7 +125,7 @@
   return (void*)str;
 }
 
-// Appends a 'bytes' string to a repeated field (a regular Ruby array for now).
+// Appends a 'bytes' string to a repeated field.
 static void* appendbytes_handler(void *closure,
                                  const void *hd,
                                  size_t size_hint) {
@@ -179,7 +208,11 @@
   size_t ofs;
   upb_fieldtype_t key_field_type;
   upb_fieldtype_t value_field_type;
-  VALUE value_field_typeclass;
+
+  // We know that we can hold this reference because the handlerdata has the
+  // same lifetime as the upb_handlers struct, and the upb_handlers struct holds
+  // a reference to the upb_msgdef, which in turn has references to its subdefs.
+  const upb_def* value_field_subdef;
 } map_handlerdata_t;
 
 // Temporary frame for map parsing: at the beginning of a map entry message, a
@@ -219,8 +252,15 @@
   VALUE key = native_slot_get(
       mapdata->key_field_type, Qnil,
       &frame->key_storage);
+
+  VALUE value_field_typeclass = Qnil;
+  if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
+      mapdata->value_field_type == UPB_TYPE_ENUM) {
+    value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
+  }
+
   VALUE value = native_slot_get(
-      mapdata->value_field_type, mapdata->value_field_typeclass,
+      mapdata->value_field_type, value_field_typeclass,
       &frame->value_storage);
 
   Map_index_set(frame->map, key, value);
@@ -251,21 +291,90 @@
                                                     MAP_VALUE_FIELD);
   assert(value_field != NULL);
   hd->value_field_type = upb_fielddef_type(value_field);
-  hd->value_field_typeclass = field_type_class(value_field);
-
-  // Ensure that value_field_typeclass is properly GC-rooted. We must do this
-  // because we hold a reference to the Ruby class in the handlerdata, which is
-  // owned by the handlers. The handlers are owned by *this* message's Ruby
-  // object, but each Ruby object is rooted independently at the def -> Ruby
-  // object map. So we have to ensure that the Ruby objects we depend on will
-  // stick around as long as we're around.
-  if (hd->value_field_typeclass != Qnil) {
-    rb_ary_push(desc->typeclass_references, hd->value_field_typeclass);
-  }
+  hd->value_field_subdef = upb_fielddef_subdef(value_field);
 
   return hd;
 }
 
+// Handlers that set primitive values in oneofs.
+#define DEFINE_ONEOF_HANDLER(type, ctype)                           \
+  static bool oneof##type##_handler(void *closure, const void *hd,  \
+                                     ctype val) {                   \
+    const oneof_handlerdata_t *oneofdata = hd;                      \
+    DEREF(closure, oneofdata->case_ofs, uint32_t) =                 \
+        oneofdata->oneof_case_num;                                  \
+    DEREF(closure, oneofdata->ofs, ctype) = val;                    \
+    return true;                                                    \
+  }
+
+DEFINE_ONEOF_HANDLER(bool,   bool)
+DEFINE_ONEOF_HANDLER(int32,  int32_t)
+DEFINE_ONEOF_HANDLER(uint32, uint32_t)
+DEFINE_ONEOF_HANDLER(float,  float)
+DEFINE_ONEOF_HANDLER(int64,  int64_t)
+DEFINE_ONEOF_HANDLER(uint64, uint64_t)
+DEFINE_ONEOF_HANDLER(double, double)
+
+#undef DEFINE_ONEOF_HANDLER
+
+// Handlers for strings in a oneof.
+static void *oneofstr_handler(void *closure,
+                              const void *hd,
+                              size_t size_hint) {
+  MessageHeader* msg = closure;
+  const oneof_handlerdata_t *oneofdata = hd;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyStringUtf8Encoding);
+  DEREF(msg, oneofdata->case_ofs, uint32_t) =
+      oneofdata->oneof_case_num;
+  DEREF(msg, oneofdata->ofs, VALUE) = str;
+  return (void*)str;
+}
+
+static void *oneofbytes_handler(void *closure,
+                                const void *hd,
+                                size_t size_hint) {
+  MessageHeader* msg = closure;
+  const oneof_handlerdata_t *oneofdata = hd;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyString8bitEncoding);
+  DEREF(msg, oneofdata->case_ofs, uint32_t) =
+      oneofdata->oneof_case_num;
+  DEREF(msg, oneofdata->ofs, VALUE) = str;
+  return (void*)str;
+}
+
+// Handler for a submessage field in a oneof.
+static void *oneofsubmsg_handler(void *closure,
+                                 const void *hd) {
+  MessageHeader* msg = closure;
+  const oneof_handlerdata_t *oneofdata = hd;
+  uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
+
+  VALUE subdesc =
+      get_def_obj((void*)oneofdata->md);
+  VALUE subklass = Descriptor_msgclass(subdesc);
+
+  if (oldcase != oneofdata->oneof_case_num ||
+      DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
+    DEREF(msg, oneofdata->ofs, VALUE) =
+        rb_class_new_instance(0, NULL, subklass);
+  }
+  // Set the oneof case *after* allocating the new class instance -- otherwise,
+  // if the Ruby GC is invoked as part of a call into the VM, it might invoke
+  // our mark routines, and our mark routines might see the case value
+  // indicating a VALUE is present and expect a valid VALUE. See comment in
+  // layout_set() for more detail: basically, the change to the value and the
+  // case must be atomic w.r.t. the Ruby VM.
+  DEREF(msg, oneofdata->case_ofs, uint32_t) =
+      oneofdata->oneof_case_num;
+
+  VALUE submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
+  MessageHeader* submsg;
+  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
+  return submsg;
+}
+
 // Set up handlers for a repeated field.
 static void add_handlers_for_repeated_field(upb_handlers *h,
                                             const upb_fielddef *f,
@@ -383,6 +492,53 @@
       offsetof(map_parse_frame_t, value_storage));
 }
 
+// Set up handlers for a oneof field.
+static void add_handlers_for_oneof_field(upb_handlers *h,
+                                         const upb_fielddef *f,
+                                         size_t offset,
+                                         size_t oneof_case_offset) {
+
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+  upb_handlerattr_sethandlerdata(
+      &attr, newoneofhandlerdata(h, offset, oneof_case_offset, f));
+
+  switch (upb_fielddef_type(f)) {
+
+#define SET_HANDLER(utype, ltype)                                 \
+  case utype:                                                     \
+    upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
+    break;
+
+    SET_HANDLER(UPB_TYPE_BOOL,   bool);
+    SET_HANDLER(UPB_TYPE_INT32,  int32);
+    SET_HANDLER(UPB_TYPE_UINT32, uint32);
+    SET_HANDLER(UPB_TYPE_ENUM,   int32);
+    SET_HANDLER(UPB_TYPE_FLOAT,  float);
+    SET_HANDLER(UPB_TYPE_INT64,  int64);
+    SET_HANDLER(UPB_TYPE_UINT64, uint64);
+    SET_HANDLER(UPB_TYPE_DOUBLE, double);
+
+#undef SET_HANDLER
+
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+      upb_handlers_setstartstr(h, f, is_bytes ?
+                               oneofbytes_handler : oneofstr_handler,
+                               &attr);
+      upb_handlers_setstring(h, f, stringdata_handler, NULL);
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
+      break;
+    }
+  }
+
+  upb_handlerattr_uninit(&attr);
+}
+
+
 static void add_handlers_for_message(const void *closure, upb_handlers *h) {
   const upb_msgdef* msgdef = upb_handlers_msgdef(h);
   Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef));
@@ -402,16 +558,20 @@
     desc->layout = create_layout(desc->msgdef);
   }
 
-  upb_msg_iter i;
-
-  for (upb_msg_begin(&i, desc->msgdef);
-       !upb_msg_done(&i);
-       upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for (upb_msg_field_begin(&i, desc->msgdef);
+       !upb_msg_field_done(&i);
+       upb_msg_field_next(&i)) {
     const upb_fielddef *f = upb_msg_iter_field(&i);
-    size_t offset = desc->layout->offsets[upb_fielddef_index(f)] +
+    size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
         sizeof(MessageHeader);
 
-    if (is_map_field(f)) {
+    if (upb_fielddef_containingoneof(f)) {
+      size_t oneof_case_offset =
+          desc->layout->fields[upb_fielddef_index(f)].case_offset +
+          sizeof(MessageHeader);
+      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
+    } else if (is_map_field(f)) {
       add_handlers_for_mapfield(h, f, offset, desc);
     } else if (upb_fielddef_isseq(f)) {
       add_handlers_for_repeated_field(h, f, offset);
@@ -804,13 +964,28 @@
   MessageHeader* msg;
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
 
-  upb_msg_iter i;
-  for (upb_msg_begin(&i, desc->msgdef);
-       !upb_msg_done(&i);
-       upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for (upb_msg_field_begin(&i, desc->msgdef);
+       !upb_msg_field_done(&i);
+       upb_msg_field_next(&i)) {
     upb_fielddef *f = upb_msg_iter_field(&i);
     uint32_t offset =
-        desc->layout->offsets[upb_fielddef_index(f)] + sizeof(MessageHeader);
+        desc->layout->fields[upb_fielddef_index(f)].offset +
+        sizeof(MessageHeader);
+
+    if (upb_fielddef_containingoneof(f)) {
+      uint32_t oneof_case_offset =
+          desc->layout->fields[upb_fielddef_index(f)].case_offset +
+          sizeof(MessageHeader);
+      // For a oneof, check that this field is actually present -- skip all the
+      // below if not.
+      if (DEREF(msg, oneof_case_offset, uint32_t) !=
+          upb_fielddef_number(f)) {
+        continue;
+      }
+      // Otherwise, fall through to the appropriate singular-field handler
+      // below.
+    }
 
     if (is_map_field(f)) {
       VALUE map = DEREF(msg, offset, VALUE);
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 4ee71d1..12e7a9d 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -683,7 +683,7 @@
       first = false;
     }
     str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
-    str = rb_str_cat2(str, " => ");
+    str = rb_str_cat2(str, "=>");
     str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
   }
 
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index ee8881d..7e58a61 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -70,6 +70,35 @@
   return ret;
 }
 
+static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
+  // If no fields in the oneof, always nil.
+  if (upb_oneofdef_numfields(o) == 0) {
+    return Qnil;
+  }
+  // Grab the first field in the oneof so we can get its layout info to find the
+  // oneof_case field.
+  upb_oneof_iter it;
+  upb_oneof_begin(&it, o);
+  assert(!upb_oneof_done(&it));
+  const upb_fielddef* first_field = upb_oneof_iter_field(&it);
+  assert(upb_fielddef_containingoneof(first_field) != NULL);
+
+  size_t case_ofs =
+      self->descriptor->layout->
+      fields[upb_fielddef_index(first_field)].case_offset;
+  uint32_t oneof_case = *((uint32_t*)(Message_data(self) + case_ofs));
+
+  if (oneof_case == ONEOF_CASE_NONE) {
+    return Qnil;
+  }
+
+  // oneof_case is a field index, so find that field.
+  const upb_fielddef* f = upb_oneofdef_itof(o, oneof_case);
+  assert(f != NULL);
+
+  return ID2SYM(rb_intern(upb_fielddef_name(f)));
+}
+
 /*
  * call-seq:
  *     Message.method_missing(*args)
@@ -82,6 +111,10 @@
  *
  *     msg.foo = 42
  *     puts msg.foo
+ *
+ * This method also provides read-only accessors for oneofs. If a oneof exists
+ * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
+ * the name of the field in that oneof that is currently set, or nil if none.
  */
 VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
   MessageHeader* self;
@@ -104,6 +137,17 @@
     name_len--;
   }
 
+  // Check for a oneof name first.
+  const upb_oneofdef* o = upb_msgdef_ntoo(self->descriptor->msgdef,
+                                          name, name_len);
+  if (o != NULL) {
+    if (setter) {
+      rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
+    }
+    return which_oneof_field(self, o);
+  }
+
+  // Otherwise, check for a field with that name.
   const upb_fielddef* f = upb_msgdef_ntof(self->descriptor->msgdef,
                                           name, name_len);
 
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index 3055270..d2d3503 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -77,8 +77,10 @@
   DescriptorPool_register(protobuf);
   Descriptor_register(protobuf);
   FieldDescriptor_register(protobuf);
+  OneofDescriptor_register(protobuf);
   EnumDescriptor_register(protobuf);
   MessageBuilderContext_register(internal);
+  OneofBuilderContext_register(internal);
   EnumBuilderContext_register(internal);
   Builder_register(internal);
   RepeatedField_register(protobuf);
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index 88ae62e..d8a327a 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -43,6 +43,7 @@
 struct FieldDescriptor;
 struct EnumDescriptor;
 struct MessageLayout;
+struct MessageField;
 struct MessageHeader;
 struct MessageBuilderContext;
 struct EnumBuilderContext;
@@ -51,10 +52,13 @@
 typedef struct DescriptorPool DescriptorPool;
 typedef struct Descriptor Descriptor;
 typedef struct FieldDescriptor FieldDescriptor;
+typedef struct OneofDescriptor OneofDescriptor;
 typedef struct EnumDescriptor EnumDescriptor;
 typedef struct MessageLayout MessageLayout;
+typedef struct MessageField MessageField;
 typedef struct MessageHeader MessageHeader;
 typedef struct MessageBuilderContext MessageBuilderContext;
+typedef struct OneofBuilderContext OneofBuilderContext;
 typedef struct EnumBuilderContext EnumBuilderContext;
 typedef struct Builder Builder;
 
@@ -120,6 +124,10 @@
   const upb_fielddef* fielddef;
 };
 
+struct OneofDescriptor {
+  const upb_oneofdef* oneofdef;
+};
+
 struct EnumDescriptor {
   const upb_enumdef* enumdef;
   VALUE module;  // begins as nil
@@ -130,6 +138,11 @@
   VALUE builder;
 };
 
+struct OneofBuilderContext {
+  VALUE descriptor;
+  VALUE builder;
+};
+
 struct EnumBuilderContext {
   VALUE enumdesc;
 };
@@ -144,6 +157,7 @@
 extern VALUE cFieldDescriptor;
 extern VALUE cEnumDescriptor;
 extern VALUE cMessageBuilderContext;
+extern VALUE cOneofBuilderContext;
 extern VALUE cEnumBuilderContext;
 extern VALUE cBuilder;
 
@@ -175,6 +189,9 @@
 VALUE Descriptor_each(VALUE _self);
 VALUE Descriptor_lookup(VALUE _self, VALUE name);
 VALUE Descriptor_add_field(VALUE _self, VALUE obj);
+VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
+VALUE Descriptor_each_oneof(VALUE _self);
+VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
 VALUE Descriptor_msgclass(VALUE _self);
 extern const rb_data_type_t _Descriptor_type;
 
@@ -199,6 +216,16 @@
 upb_fieldtype_t ruby_to_fieldtype(VALUE type);
 VALUE fieldtype_to_ruby(upb_fieldtype_t type);
 
+void OneofDescriptor_mark(void* _self);
+void OneofDescriptor_free(void* _self);
+VALUE OneofDescriptor_alloc(VALUE klass);
+void OneofDescriptor_register(VALUE module);
+OneofDescriptor* ruby_to_OneofDescriptor(VALUE value);
+VALUE OneofDescriptor_name(VALUE _self);
+VALUE OneofDescriptor_name_set(VALUE _self, VALUE value);
+VALUE OneofDescriptor_add_field(VALUE _self, VALUE field);
+VALUE OneofDescriptor_each(VALUE _self, VALUE field);
+
 void EnumDescriptor_mark(void* _self);
 void EnumDescriptor_free(void* _self);
 VALUE EnumDescriptor_alloc(VALUE klass);
@@ -225,6 +252,17 @@
 VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
 VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
 VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name);
+
+void OneofBuilderContext_mark(void* _self);
+void OneofBuilderContext_free(void* _self);
+VALUE OneofBuilderContext_alloc(VALUE klass);
+void OneofBuilderContext_register(VALUE module);
+OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value);
+VALUE OneofBuilderContext_initialize(VALUE _self,
+                                     VALUE descriptor,
+                                     VALUE builder);
+VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
 
 void EnumBuilderContext_mark(void* _self);
 void EnumBuilderContext_free(void* _self);
@@ -247,13 +285,22 @@
 // Native slot storage abstraction.
 // -----------------------------------------------------------------------------
 
-#define NATIVE_SLOT_MAX_SIZE sizeof(void*)
+#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
 
 size_t native_slot_size(upb_fieldtype_t type);
 void native_slot_set(upb_fieldtype_t type,
                      VALUE type_class,
                      void* memory,
                      VALUE value);
+// Atomically (with respect to Ruby VM calls) either update the value and set a
+// oneof case, or do neither. If |case_memory| is null, then no case value is
+// set.
+void native_slot_set_value_and_case(upb_fieldtype_t type,
+                                    VALUE type_class,
+                                    void* memory,
+                                    VALUE value,
+                                    uint32_t* case_memory,
+                                    uint32_t case_number);
 VALUE native_slot_get(upb_fieldtype_t type,
                       VALUE type_class,
                       const void* memory);
@@ -275,6 +322,11 @@
 #define MAP_KEY_FIELD 1
 #define MAP_VALUE_FIELD 2
 
+// Oneof case slot value to indicate that no oneof case is set. The value `0` is
+// safe because field numbers are used as case identifiers, and no field can
+// have a number of 0.
+#define ONEOF_CASE_NONE 0
+
 // These operate on a map field (i.e., a repeated field of submessages whose
 // submessage type is a map-entry msgdef).
 bool is_map_field(const upb_fielddef* field);
@@ -384,9 +436,16 @@
 // Message layout / storage.
 // -----------------------------------------------------------------------------
 
+#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
+
+struct MessageField {
+  size_t offset;
+  size_t case_offset;  // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
+};
+
 struct MessageLayout {
   const upb_msgdef* msgdef;
-  size_t* offsets;
+  MessageField* fields;
   size_t size;
 };
 
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index 6e3f0bc..8cf2e29 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -318,6 +318,29 @@
 
 /*
  * call-seq:
+ *     RepeatedField.to_ary => array
+ *
+ * Used when converted implicitly into array, e.g. compared to an Array.
+ * Also called as a fallback of Object#to_a
+ */
+VALUE RepeatedField_to_ary(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+
+  size_t elem_size = native_slot_size(field_type);
+  size_t off = 0;
+  VALUE ary = rb_ary_new2(self->size);
+  for (int i = 0; i < self->size; i++, off += elem_size) {
+    void* mem = ((uint8_t *)self->elements) + off;
+    VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
+
+    rb_ary_push(ary, elem);
+  }
+  return ary;
+}
+
+/*
+ * call-seq:
  *     RepeatedField.==(other) => boolean
  *
  * Compares this repeated field to another. Repeated fields are equal if their
@@ -335,15 +358,9 @@
   }
   RepeatedField* self = ruby_to_RepeatedField(_self);
 
-  // Inefficient but workable: to support comparison to a generic array, we
-  // build a temporary RepeatedField of our type.
   if (TYPE(_other) == T_ARRAY) {
-    VALUE new_rptfield = RepeatedField_new_this_type(_self);
-    for (int i = 0; i < RARRAY_LEN(_other); i++) {
-      VALUE elem = rb_ary_entry(_other, i);
-      RepeatedField_push(new_rptfield, elem);
-    }
-    _other = new_rptfield;
+    VALUE self_ary = RepeatedField_to_ary(_self);
+    return rb_equal(self_ary, _other);
   }
 
   RepeatedField* other = ruby_to_RepeatedField(_other);
@@ -401,29 +418,8 @@
  * representation computed by its own #inspect method.
  */
 VALUE RepeatedField_inspect(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-
-  VALUE str = rb_str_new2("[");
-
-  bool first = true;
-
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  for (int i = 0; i < self->size; i++, off += elem_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, field_type_class, mem);
-    if (!first) {
-      str = rb_str_cat2(str, ", ");
-    } else {
-      first = false;
-    }
-    str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
-  }
-
-  str = rb_str_cat2(str, "]");
-  return str;
+  VALUE self_ary = RepeatedField_to_ary(_self);
+  return rb_funcall(self_ary, rb_intern("inspect"), 0);
 }
 
 /*
@@ -594,6 +590,7 @@
   // Also define #clone so that we don't inherit Object#clone.
   rb_define_method(klass, "clone", RepeatedField_dup, 0);
   rb_define_method(klass, "==", RepeatedField_eq, 1);
+  rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
   rb_define_method(klass, "hash", RepeatedField_hash, 0);
   rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
   rb_define_method(klass, "+", RepeatedField_plus, 1);
diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c
index 14f49d4..5b1549d 100644
--- a/ruby/ext/google/protobuf_c/storage.c
+++ b/ruby/ext/google/protobuf_c/storage.c
@@ -109,6 +109,17 @@
 
 void native_slot_set(upb_fieldtype_t type, VALUE type_class,
                      void* memory, VALUE value) {
+  native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
+}
+
+void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
+                                    void* memory, VALUE value,
+                                    uint32_t* case_memory,
+                                    uint32_t case_number) {
+  // Note that in order to atomically change the value in memory and the case
+  // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
+  // all Ruby VM calls are complete. The case is then set at the bottom of this
+  // function.
   switch (type) {
     case UPB_TYPE_FLOAT:
       if (!is_ruby_num(value)) {
@@ -198,6 +209,10 @@
     default:
       break;
   }
+
+  if (case_memory != NULL) {
+    *case_memory = case_number;
+  }
 }
 
 VALUE native_slot_get(upb_fieldtype_t type,
@@ -366,24 +381,94 @@
 // Memory layout management.
 // -----------------------------------------------------------------------------
 
+static size_t align_up_to(size_t offset, size_t granularity) {
+  // Granularity must be a power of two.
+  return (offset + granularity - 1) & ~(granularity - 1);
+}
+
 MessageLayout* create_layout(const upb_msgdef* msgdef) {
   MessageLayout* layout = ALLOC(MessageLayout);
   int nfields = upb_msgdef_numfields(msgdef);
-  layout->offsets = ALLOC_N(size_t, nfields);
+  layout->fields = ALLOC_N(MessageField, nfields);
 
-  upb_msg_iter it;
+  upb_msg_field_iter it;
   size_t off = 0;
-  for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
+  for (upb_msg_field_begin(&it, msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
+
+    if (upb_fielddef_containingoneof(field)) {
+      // Oneofs are handled separately below.
+      continue;
+    }
+
+    // Allocate |field_size| bytes for this field in the layout.
     size_t field_size = 0;
     if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
       field_size = sizeof(VALUE);
     } else {
       field_size = native_slot_size(upb_fielddef_type(field));
     }
-    // align current offset
+    // Align current offset up to |size| granularity.
+    off = align_up_to(off, field_size);
+    layout->fields[upb_fielddef_index(field)].offset = off;
+    layout->fields[upb_fielddef_index(field)].case_offset = MESSAGE_FIELD_NO_CASE;
+    off += field_size;
+  }
+
+  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
+  // one slot per oneof.
+  //
+  // We assign all value slots first, then pack the 'case' fields at the end,
+  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
+  // bytes respectively and we want to avoid alignment overhead.
+  //
+  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
+  // space for oneof cases is conceptually as wide as field tag numbers. In
+  // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
+  // members (8 or 16 bits respectively), so conceivably we could assign
+  // consecutive case numbers and then pick a smaller oneof case slot size, but
+  // the complexity to implement this indirection is probably not worthwhile.
+  upb_msg_oneof_iter oit;
+  for (upb_msg_oneof_begin(&oit, msgdef);
+       !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
+
+    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
+    // all fields.
+    size_t field_size = NATIVE_SLOT_MAX_SIZE;
+    // Align the offset.
+    off = align_up_to(off, field_size);
+    // Assign all fields in the oneof this same offset.
+    upb_oneof_iter fit;
+    for (upb_oneof_begin(&fit, oneof);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* field = upb_oneof_iter_field(&fit);
+      layout->fields[upb_fielddef_index(field)].offset = off;
+    }
+    off += field_size;
+  }
+
+  // Now the case fields.
+  for (upb_msg_oneof_begin(&oit, msgdef);
+       !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
+
+    size_t field_size = sizeof(uint32_t);
+    // Align the offset.
     off = (off + field_size - 1) & ~(field_size - 1);
-    layout->offsets[upb_fielddef_index(field)] = off;
+    // Assign all fields in the oneof this same offset.
+    upb_oneof_iter fit;
+    for (upb_oneof_begin(&fit, oneof);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* field = upb_oneof_iter_field(&fit);
+      layout->fields[upb_fielddef_index(field)].case_offset = off;
+    }
     off += field_size;
   }
 
@@ -396,7 +481,7 @@
 }
 
 void free_layout(MessageLayout* layout) {
-  xfree(layout->offsets);
+  xfree(layout->fields);
   upb_msgdef_unref(layout->msgdef, &layout->msgdef);
   xfree(layout);
 }
@@ -415,12 +500,35 @@
   return type_class;
 }
 
+static void* slot_memory(MessageLayout* layout,
+                         const void* storage,
+                         const upb_fielddef* field) {
+  return ((uint8_t *)storage) +
+      layout->fields[upb_fielddef_index(field)].offset;
+}
+
+static uint32_t* slot_oneof_case(MessageLayout* layout,
+                                 const void* storage,
+                                 const upb_fielddef* field) {
+  return (uint32_t *)(((uint8_t *)storage) +
+      layout->fields[upb_fielddef_index(field)].case_offset);
+}
+
+
 VALUE layout_get(MessageLayout* layout,
                  const void* storage,
                  const upb_fielddef* field) {
-  void* memory = ((uint8_t *)storage) +
-      layout->offsets[upb_fielddef_index(field)];
-  if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+  void* memory = slot_memory(layout, storage, field);
+  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+  if (upb_fielddef_containingoneof(field)) {
+    if (*oneof_case != upb_fielddef_number(field)) {
+      return Qnil;
+    }
+    return native_slot_get(upb_fielddef_type(field),
+                           field_type_class(field),
+                           memory);
+  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
     return *((VALUE *)memory);
   } else {
     return native_slot_get(upb_fielddef_type(field),
@@ -484,9 +592,33 @@
                 void* storage,
                 const upb_fielddef* field,
                 VALUE val) {
-  void* memory = ((uint8_t *)storage) +
-      layout->offsets[upb_fielddef_index(field)];
-  if (is_map_field(field)) {
+  void* memory = slot_memory(layout, storage, field);
+  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+  if (upb_fielddef_containingoneof(field)) {
+    if (val == Qnil) {
+      // Assigning nil to a oneof field clears the oneof completely.
+      *oneof_case = ONEOF_CASE_NONE;
+      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+    } else {
+      // The transition between field types for a single oneof (union) slot is
+      // somewhat complex because we need to ensure that a GC triggered at any
+      // point by a call into the Ruby VM sees a valid state for this field and
+      // does not either go off into the weeds (following what it thinks is a
+      // VALUE but is actually a different field type) or miss an object (seeing
+      // what it thinks is a primitive field but is actually a VALUE for the new
+      // field type).
+      //
+      // In order for the transition to be safe, the oneof case slot must be in
+      // sync with the value slot whenever the Ruby VM has been called. Thus, we
+      // use native_slot_set_value_and_case(), which ensures that both the value
+      // and case number are altered atomically (w.r.t. the Ruby VM).
+      native_slot_set_value_and_case(
+          upb_fielddef_type(field), field_type_class(field),
+          memory, val,
+          oneof_case, upb_fielddef_number(field));
+    }
+  } else if (is_map_field(field)) {
     check_map_field_type(val, field);
     DEREF(memory, VALUE) = val;
   } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
@@ -500,15 +632,18 @@
 
 void layout_init(MessageLayout* layout,
                  void* storage) {
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
-    void* memory = ((uint8_t *)storage) +
-        layout->offsets[upb_fielddef_index(field)];
+    void* memory = slot_memory(layout, storage, field);
+    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
 
-    if (is_map_field(field)) {
+    if (upb_fielddef_containingoneof(field)) {
+      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+      *oneof_case = ONEOF_CASE_NONE;
+    } else if (is_map_field(field)) {
       VALUE map = Qnil;
 
       const upb_fielddef* key_field = map_field_key(field);
@@ -555,15 +690,19 @@
 }
 
 void layout_mark(MessageLayout* layout, void* storage) {
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
-    void* memory = ((uint8_t *)storage) +
-        layout->offsets[upb_fielddef_index(field)];
+    void* memory = slot_memory(layout, storage, field);
+    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
 
-    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+    if (upb_fielddef_containingoneof(field)) {
+      if (*oneof_case == upb_fielddef_number(field)) {
+        native_slot_mark(upb_fielddef_type(field), memory);
+      }
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
       rb_gc_mark(DEREF(memory, VALUE));
     } else {
       native_slot_mark(upb_fielddef_type(field), memory);
@@ -572,17 +711,23 @@
 }
 
 void layout_dup(MessageLayout* layout, void* to, void* from) {
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
-    void* to_memory = ((uint8_t *)to) +
-        layout->offsets[upb_fielddef_index(field)];
-    void* from_memory = ((uint8_t *)from) +
-        layout->offsets[upb_fielddef_index(field)];
 
-    if (is_map_field(field)) {
+    void* to_memory = slot_memory(layout, to, field);
+    uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
+    void* from_memory = slot_memory(layout, from, field);
+    uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*from_oneof_case == upb_fielddef_number(field)) {
+        *to_oneof_case = *from_oneof_case;
+        native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
+      }
+    } else if (is_map_field(field)) {
       DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
     } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
       DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
@@ -593,17 +738,23 @@
 }
 
 void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
-    void* to_memory = ((uint8_t *)to) +
-        layout->offsets[upb_fielddef_index(field)];
-    void* from_memory = ((uint8_t *)from) +
-        layout->offsets[upb_fielddef_index(field)];
 
-    if (is_map_field(field)) {
+    void* to_memory = slot_memory(layout, to, field);
+    uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
+    void* from_memory = slot_memory(layout, from, field);
+    uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*from_oneof_case == upb_fielddef_number(field)) {
+        *to_oneof_case = *from_oneof_case;
+        native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
+      }
+    } else if (is_map_field(field)) {
       DEREF(to_memory, VALUE) =
           Map_deep_copy(DEREF(from_memory, VALUE));
     } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
@@ -616,22 +767,35 @@
 }
 
 VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
-  upb_msg_iter it;
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
-    void* msg1_memory = ((uint8_t *)msg1) +
-        layout->offsets[upb_fielddef_index(field)];
-    void* msg2_memory = ((uint8_t *)msg2) +
-        layout->offsets[upb_fielddef_index(field)];
 
-    if (is_map_field(field)) {
-      return Map_eq(DEREF(msg1_memory, VALUE),
-                    DEREF(msg2_memory, VALUE));
+    void* msg1_memory = slot_memory(layout, msg1, field);
+    uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
+    void* msg2_memory = slot_memory(layout, msg2, field);
+    uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*msg1_oneof_case != *msg2_oneof_case ||
+          (*msg1_oneof_case == upb_fielddef_number(field) &&
+           !native_slot_eq(upb_fielddef_type(field),
+                           msg1_memory,
+                           msg2_memory))) {
+        return Qfalse;
+      }
+    } else if (is_map_field(field)) {
+      if (!Map_eq(DEREF(msg1_memory, VALUE),
+                  DEREF(msg2_memory, VALUE))) {
+        return Qfalse;
+      }
     } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      return RepeatedField_eq(DEREF(msg1_memory, VALUE),
-                              DEREF(msg2_memory, VALUE));
+      if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
+                            DEREF(msg2_memory, VALUE))) {
+        return Qfalse;
+      }
     } else {
       if (!native_slot_eq(upb_fielddef_type(field),
                           msg1_memory, msg2_memory)) {
@@ -643,12 +807,12 @@
 }
 
 VALUE layout_hash(MessageLayout* layout, void* storage) {
-  upb_msg_iter it;
+  upb_msg_field_iter it;
   st_index_t h = rb_hash_start(0);
   VALUE hash_sym = rb_intern("hash");
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
     VALUE field_val = layout_get(layout, storage, field);
     h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
@@ -661,11 +825,11 @@
 VALUE layout_inspect(MessageLayout* layout, void* storage) {
   VALUE str = rb_str_new2("");
 
-  upb_msg_iter it;
+  upb_msg_field_iter it;
   bool first = true;
-  for (upb_msg_begin(&it, layout->msgdef);
-       !upb_msg_done(&it);
-       upb_msg_next(&it)) {
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
     const upb_fielddef* field = upb_msg_iter_field(&it);
     VALUE field_val = layout_get(layout, storage, field);
 
diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c
index 571c809..20bd76b 100644
--- a/ruby/ext/google/protobuf_c/upb.c
+++ b/ruby/ext/google/protobuf_c/upb.c
@@ -210,6 +210,21 @@
     upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f));
   }
 
+  // Ensure that MapEntry submessages only appear as repeated fields, not
+  // optional/required (singular) fields.
+  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+      upb_fielddef_msgsubdef(f) != NULL) {
+    const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
+    if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) {
+      upb_status_seterrf(s,
+                         "Field %s refers to mapentry message but is not "
+                         "a repeated field",
+                         upb_fielddef_name(f) ? upb_fielddef_name(f) :
+                         "(unnamed)");
+      return false;
+    }
+  }
+
   return true;
 }
 
@@ -247,10 +262,12 @@
   upb_fielddef **fields = malloc(n * sizeof(*fields));
   if (!fields) return false;
 
-  upb_msg_iter j;
+  upb_msg_field_iter j;
   int i;
   m->submsg_field_count = 0;
-  for(i = 0, upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j), i++) {
+  for(i = 0, upb_msg_field_begin(&j, m);
+      !upb_msg_field_done(&j);
+      upb_msg_field_next(&j), i++) {
     upb_fielddef *f = upb_msg_iter_field(&j);
     assert(f->msg.def == m);
     if (!upb_validate_field(f, s)) {
@@ -286,7 +303,9 @@
   upb_selector_t sel;
   upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
   upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v);
-  for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) {
+  for(upb_msg_field_begin(&j, m);
+      !upb_msg_field_done(&j);
+      upb_msg_field_next(&j)) {
     upb_fielddef *f = upb_msg_iter_field(&j);
     // These calls will assert-fail in upb_table if the value already exists.
     TRY(UPB_HANDLER_INT32);
@@ -544,6 +563,9 @@
   if (upb_fielddef_containingtype(f)) {
     visit(r, UPB_UPCAST2(upb_fielddef_containingtype(f)), closure);
   }
+  if (upb_fielddef_containingoneof(f)) {
+    visit(r, UPB_UPCAST2(upb_fielddef_containingoneof(f)), closure);
+  }
   if (upb_fielddef_subdef(f)) {
     visit(r, UPB_UPCAST(upb_fielddef_subdef(f)), closure);
   }
@@ -619,6 +641,7 @@
   }
   f->msg.def = NULL;
   f->sub.def = NULL;
+  f->oneof = NULL;
   f->subdef_is_symbolic = false;
   f->msg_is_symbolic = false;
   f->label_ = UPB_LABEL_OPTIONAL;
@@ -748,6 +771,10 @@
   return f->msg_is_symbolic ? NULL : f->msg.def;
 }
 
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+  return f->oneof;
+}
+
 upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
   return (upb_msgdef*)upb_fielddef_containingtype(f);
 }
@@ -776,6 +803,10 @@
 }
 
 bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
+  if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) {
+    upb_status_seterrmsg(s, "Already added to message or oneof");
+    return false;
+  }
   return upb_def_setfullname(UPB_UPCAST(f), name, s);
 }
 
@@ -1226,6 +1257,11 @@
   return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
 }
 
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
 bool upb_fielddef_hassubdef(const upb_fielddef *f) {
   return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
 }
@@ -1247,15 +1283,25 @@
 static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
                      void *closure) {
   const upb_msgdef *m = (const upb_msgdef*)r;
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     upb_fielddef *f = upb_msg_iter_field(&i);
     visit(r, UPB_UPCAST2(f), closure);
   }
+  upb_msg_oneof_iter o;
+  for(upb_msg_oneof_begin(&o, m);
+      !upb_msg_oneof_done(&o);
+      upb_msg_oneof_next(&o)) {
+    upb_oneofdef *f = upb_msg_iter_oneof(&o);
+    visit(r, UPB_UPCAST2(f), closure);
+  }
 }
 
 static void freemsg(upb_refcounted *r) {
   upb_msgdef *m = (upb_msgdef*)r;
+  upb_strtable_uninit(&m->ntoo);
   upb_strtable_uninit(&m->ntof);
   upb_inttable_uninit(&m->itof);
   upb_def_uninit(UPB_UPCAST(m));
@@ -1267,14 +1313,17 @@
   upb_msgdef *m = malloc(sizeof(*m));
   if (!m) return NULL;
   if (!upb_def_init(UPB_UPCAST(m), UPB_DEF_MSG, &vtbl, owner)) goto err2;
-  if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2;
-  if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1;
+  if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3;
+  if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1;
   m->map_entry = false;
   return m;
 
 err1:
-  upb_inttable_uninit(&m->itof);
+  upb_strtable_uninit(&m->ntof);
 err2:
+  upb_inttable_uninit(&m->itof);
+err3:
   free(m);
   return NULL;
 }
@@ -1286,14 +1335,28 @@
                                 upb_def_fullname(UPB_UPCAST(m)), NULL);
   newm->map_entry = m->map_entry;
   UPB_ASSERT_VAR(ok, ok);
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
+    // Fields in oneofs are dup'd below.
+    if (upb_fielddef_containingoneof(f)) continue;
     if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
       upb_msgdef_unref(newm, owner);
       return NULL;
     }
   }
+  upb_msg_oneof_iter o;
+  for(upb_msg_oneof_begin(&o, m);
+      !upb_msg_oneof_done(&o);
+      upb_msg_oneof_next(&o)) {
+    upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f);
+    if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) {
+      upb_msgdef_unref(newm, owner);
+      return NULL;
+    }
+  }
   return newm;
 }
 
@@ -1332,6 +1395,35 @@
   return upb_def_setfullname(UPB_UPCAST(m), fullname, s);
 }
 
+// Helper: check that the field |f| is safe to add to msgdef |m|. Set an error
+// on status |s| and return false if not.
+static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
+                            upb_status *s) {
+  if (upb_fielddef_containingtype(f) != NULL) {
+    upb_status_seterrmsg(s, "fielddef already belongs to a message");
+    return false;
+  } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "field name or number were not set");
+    return false;
+  } else if (upb_msgdef_ntofz(m, upb_fielddef_name(f)) ||
+             upb_msgdef_itof(m, upb_fielddef_number(f))) {
+    upb_status_seterrmsg(s, "duplicate field name or number for field");
+    return false;
+  }
+  return true;
+}
+
+static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) {
+  release_containingtype(f);
+  f->msg.def = m;
+  f->msg_is_symbolic = false;
+  upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
+  upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
+  upb_ref2(f, m);
+  upb_ref2(m, f);
+  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+}
+
 bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
                          upb_status *s) {
   // TODO: extensions need to have a separate namespace, because proto2 allows a
@@ -1345,28 +1437,65 @@
   // We also need to validate that the field number is in an extension range iff
   // it is an extension.
 
+  // This method is idempotent. Check if |f| is already part of this msgdef and
+  // return immediately if so.
+  if (upb_fielddef_containingtype(f) == m) {
+    return true;
+  }
+
   // Check constraints for all fields before performing any action.
-  if (upb_fielddef_containingtype(f) != NULL) {
-    upb_status_seterrmsg(s, "fielddef already belongs to a message");
+  if (!check_field_add(m, f, s)) {
     return false;
-  } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
-    upb_status_seterrmsg(s, "field name or number were not set");
-    return false;
-  } else if(upb_msgdef_itof(m, upb_fielddef_number(f)) ||
-            upb_msgdef_ntofz(m, upb_fielddef_name(f))) {
-    upb_status_seterrmsg(s, "duplicate field name or number");
+  } else if (upb_fielddef_containingoneof(f) != NULL) {
+    // Fields in a oneof can only be added by adding the oneof to the msgdef.
+    upb_status_seterrmsg(s, "fielddef is part of a oneof");
     return false;
   }
 
   // Constraint checks ok, perform the action.
-  release_containingtype(f);
-  f->msg.def = m;
-  f->msg_is_symbolic = false;
-  upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
-  upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
-  upb_ref2(f, m);
-  upb_ref2(m, f);
-  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+  add_field(m, f, ref_donor);
+  return true;
+}
+
+bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
+                         upb_status *s) {
+  // Check various conditions that would prevent this oneof from being added.
+  if (upb_oneofdef_containingtype(o)) {
+    upb_status_seterrmsg(s, "oneofdef already belongs to a message");
+    return false;
+  } else if (upb_oneofdef_name(o) == NULL) {
+    upb_status_seterrmsg(s, "oneofdef name was not set");
+    return false;
+  } else if (upb_msgdef_ntooz(m, upb_oneofdef_name(o))) {
+    upb_status_seterrmsg(s, "duplicate oneof name");
+    return false;
+  }
+
+  // Check that all of the oneof's fields do not conflict with names or numbers
+  // of fields already in the message.
+  upb_oneof_iter it;
+  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
+    const upb_fielddef *f = upb_oneof_iter_field(&it);
+    if (!check_field_add(m, f, s)) {
+      return false;
+    }
+  }
+
+  // Everything checks out -- commit now.
+
+  // Add oneof itself first.
+  o->parent = m;
+  upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o));
+  upb_ref2(o, m);
+  upb_ref2(m, o);
+
+  // Add each field of the oneof directly to the msgdef.
+  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
+    upb_fielddef *f = upb_oneof_iter_field(&it);
+    add_field(m, f, NULL);
+  }
+
+  if (ref_donor) upb_oneofdef_unref(o, ref_donor);
 
   return true;
 }
@@ -1384,10 +1513,21 @@
       upb_value_getptr(val) : NULL;
 }
 
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+  return upb_strtable_lookup2(&m->ntoo, name, len, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
 int upb_msgdef_numfields(const upb_msgdef *m) {
   return upb_strtable_count(&m->ntof);
 }
 
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+  return upb_strtable_count(&m->ntoo);
+}
+
 void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
   assert(!upb_msgdef_isfrozen(m));
   m->map_entry = map_entry;
@@ -1397,19 +1537,246 @@
   return m->map_entry;
 }
 
-void upb_msg_begin(upb_msg_iter *iter, const upb_msgdef *m) {
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
   upb_inttable_begin(iter, &m->itof);
 }
 
-void upb_msg_next(upb_msg_iter *iter) { upb_inttable_next(iter); }
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
 
-bool upb_msg_done(const upb_msg_iter *iter) { return upb_inttable_done(iter); }
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+  return upb_inttable_done(iter);
+}
 
-upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter) {
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
   return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
 }
 
-void upb_msg_iter_setdone(upb_msg_iter *iter) {
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+  upb_strtable_begin(iter, &m->ntoo);
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { upb_strtable_next(iter); }
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+  return upb_strtable_done(iter);
+}
+
+upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+  return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter));
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+  upb_strtable_iter_setdone(iter);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const upb_oneofdef *o = (const upb_oneofdef*)r;
+  upb_oneof_iter i;
+  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+    const upb_fielddef *f = upb_oneof_iter_field(&i);
+    visit(r, UPB_UPCAST2(f), closure);
+  }
+  if (o->parent) {
+    visit(r, UPB_UPCAST2(o->parent), closure);
+  }
+}
+
+static void freeoneof(upb_refcounted *r) {
+  upb_oneofdef *o = (upb_oneofdef*)r;
+  upb_strtable_uninit(&o->ntof);
+  upb_inttable_uninit(&o->itof);
+  upb_def_uninit(UPB_UPCAST(o));
+  free(o);
+}
+
+upb_oneofdef *upb_oneofdef_new(const void *owner) {
+  static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof};
+  upb_oneofdef *o = malloc(sizeof(*o));
+  o->parent = NULL;
+  if (!o) return NULL;
+  if (!upb_def_init(UPB_UPCAST(o), UPB_DEF_ONEOF, &vtbl, owner)) goto err2;
+  if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1;
+  return o;
+
+err1:
+  upb_inttable_uninit(&o->itof);
+err2:
+  free(o);
+  return NULL;
+}
+
+upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
+  upb_oneofdef *newo = upb_oneofdef_new(owner);
+  if (!newo) return NULL;
+  bool ok = upb_def_setfullname(UPB_UPCAST(newo),
+                                upb_def_fullname(UPB_UPCAST(o)), NULL);
+  UPB_ASSERT_VAR(ok, ok);
+  upb_oneof_iter i;
+  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+    upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
+    if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
+      upb_oneofdef_unref(newo, owner);
+      return NULL;
+    }
+  }
+  return newo;
+}
+
+bool upb_oneofdef_isfrozen(const upb_oneofdef *o) {
+  return upb_def_isfrozen(UPB_UPCAST(o));
+}
+
+void upb_oneofdef_ref(const upb_oneofdef *o, const void *owner) {
+  upb_def_ref(UPB_UPCAST(o), owner);
+}
+
+void upb_oneofdef_unref(const upb_oneofdef *o, const void *owner) {
+  upb_def_unref(UPB_UPCAST(o), owner);
+}
+
+void upb_oneofdef_donateref(const upb_oneofdef *o, const void *from,
+                           const void *to) {
+  upb_def_donateref(UPB_UPCAST(o), from, to);
+}
+
+void upb_oneofdef_checkref(const upb_oneofdef *o, const void *owner) {
+  upb_def_checkref(UPB_UPCAST(o), owner);
+}
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) {
+  return upb_def_fullname(UPB_UPCAST(o));
+}
+
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname,
+                             upb_status *s) {
+  if (upb_oneofdef_containingtype(o)) {
+    upb_status_seterrmsg(s, "oneof already added to a message");
+    return false;
+  }
+  return upb_def_setfullname(UPB_UPCAST(o), fullname, s);
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+  return o->parent;
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+  return upb_strtable_count(&o->ntof);
+}
+
+bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
+                           const void *ref_donor,
+                           upb_status *s) {
+  assert(!upb_oneofdef_isfrozen(o));
+  assert(!o->parent || !upb_msgdef_isfrozen(o->parent));
+
+  // This method is idempotent. Check if |f| is already part of this oneofdef
+  // and return immediately if so.
+  if (upb_fielddef_containingoneof(f) == o) {
+    return true;
+  }
+
+  // The field must have an OPTIONAL label.
+  if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+    upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label");
+    return false;
+  }
+
+  // Check that no field with this name or number exists already in the oneof.
+  // Also check that the field is not already part of a oneof.
+  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "field name or number were not set");
+    return false;
+  } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) ||
+             upb_oneofdef_ntofz(o, upb_fielddef_name(f))) {
+    upb_status_seterrmsg(s, "duplicate field name or number");
+    return false;
+  } else if (upb_fielddef_containingoneof(f) != NULL) {
+    upb_status_seterrmsg(s, "fielddef already belongs to a oneof");
+    return false;
+  }
+
+  // We allow adding a field to the oneof either if the field is not part of a
+  // msgdef, or if it is and we are also part of the same msgdef.
+  if (o->parent == NULL) {
+    // If we're not in a msgdef, the field cannot be either. Otherwise we would
+    // need to magically add this oneof to a msgdef to remain consistent, which
+    // is surprising behavior.
+    if (upb_fielddef_containingtype(f) != NULL) {
+      upb_status_seterrmsg(s, "fielddef already belongs to a message, but "
+                              "oneof does not");
+      return false;
+    }
+  } else {
+    // If we're in a msgdef, the user can add fields that either aren't in any
+    // msgdef (in which case they're added to our msgdef) or already a part of
+    // our msgdef.
+    if (upb_fielddef_containingtype(f) != NULL &&
+        upb_fielddef_containingtype(f) != o->parent) {
+      upb_status_seterrmsg(s, "fielddef belongs to a different message "
+                              "than oneof");
+      return false;
+    }
+  }
+
+  // Commit phase. First add the field to our parent msgdef, if any, because
+  // that may fail; then add the field to our own tables.
+
+  if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) {
+    if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) {
+      return false;
+    }
+  }
+
+  release_containingtype(f);
+  f->oneof = o;
+  upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f));
+  upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f));
+  upb_ref2(f, o);
+  upb_ref2(o, f);
+  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+
+  return true;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup32(&o->itof, num, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+  upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+  upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
   upb_inttable_iter_setdone(iter);
 }
 /*
@@ -1452,8 +1819,10 @@
 static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
                           void *closure) {
   const upb_handlers *h = (const upb_handlers*)r;
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, h->msg);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     upb_fielddef *f = upb_msg_iter_field(&i);
     if (!upb_fielddef_issubmsg(f)) continue;
     const upb_handlers *sub = upb_handlers_getsubhandlers(h, f);
@@ -1482,8 +1851,10 @@
 
   // For each submessage field, get or create a handlers object and set it as
   // the subhandlers.
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     upb_fielddef *f = upb_msg_iter_field(&i);
     if (!upb_fielddef_issubmsg(f)) continue;
 
@@ -1840,8 +2211,10 @@
 
     // Check that there are no closure mismatches due to missing Start* handlers
     // or subhandlers with different type-level types.
-    upb_msg_iter j;
-    for(upb_msg_begin(&j, h->msg); !upb_msg_done(&j); upb_msg_next(&j)) {
+    upb_msg_field_iter j;
+    for(upb_msg_field_begin(&j, h->msg);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
 
       const upb_fielddef *f = upb_msg_iter_field(&j);
       if (upb_fielddef_isseq(f)) {
@@ -3114,8 +3487,10 @@
     // For messages, continue the recursion by visiting all subdefs.
     const upb_msgdef *m = upb_dyncast_msgdef(def);
     if (m) {
-      upb_msg_iter i;
-      for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+      upb_msg_field_iter i;
+      for(upb_msg_field_begin(&i, m);
+          !upb_msg_field_done(&i);
+          upb_msg_field_next(&i)) {
         upb_fielddef *f = upb_msg_iter_field(&i);
         if (!upb_fielddef_hassubdef(f)) continue;
         // |= to avoid short-circuit; we need its side-effects.
@@ -3268,8 +3643,10 @@
     // Type names are resolved relative to the message in which they appear.
     const char *base = upb_msgdef_fullname(m);
 
-    upb_msg_iter j;
-    for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) {
+    upb_msg_field_iter j;
+    for(upb_msg_field_begin(&j, m);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
       upb_fielddef *f = upb_msg_iter_field(&j);
       const char *name = upb_fielddef_subdefname(f);
       if (name && !upb_fielddef_subdef(f)) {
@@ -6462,8 +6839,10 @@
   putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
  label(c, LABEL_FIELD);
   uint32_t* start_pc = c->pc;
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     const upb_fielddef *f = upb_msg_iter_field(&i);
     upb_fieldtype_t type = upb_fielddef_type(f);
 
@@ -6513,9 +6892,11 @@
   newmethod(h, c->group);
 
   // Find submethods.
-  upb_msg_iter i;
+  upb_msg_field_iter i;
   const upb_msgdef *md = upb_handlers_msgdef(h);
-  for(upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) {
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     const upb_fielddef *f = upb_msg_iter_field(&i);
     const upb_handlers *sub_h;
     if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
@@ -6557,7 +6938,7 @@
 }
 
 
-/* JIT setup. ******************************************************************/
+/* JIT setup. *****************************************************************/
 
 #ifdef UPB_USE_JIT_X64
 
@@ -7980,8 +8361,10 @@
   upb_handlers_setendmsg(h, endmsg, NULL);
 
   const upb_msgdef *m = upb_handlers_msgdef(h);
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     const upb_fielddef *f = upb_msg_iter_field(&i);
     bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
                   upb_fielddef_packed(f);
@@ -8443,8 +8826,10 @@
   upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
   upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
 
-  upb_msg_iter i;
-  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
     upb_fielddef *f = upb_msg_iter_field(&i);
     upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
     upb_handlerattr_sethandlerdata(&attr, f);
@@ -8857,6 +9242,7 @@
 //      the true value in a contiguous buffer.
 
 static void assert_accumulate_empty(upb_json_parser *p) {
+  UPB_UNUSED(p);
   assert(p->accumulated == NULL);
   assert(p->accumulated_len == 0);
 }
@@ -9141,11 +9527,17 @@
   capture_begin(p, ptr);
 }
 
+static bool parse_number(upb_json_parser *p);
+
 static bool end_number(upb_json_parser *p, const char *ptr) {
   if (!capture_end(p, ptr)) {
     return false;
   }
 
+  return parse_number(p);
+}
+
+static bool parse_number(upb_json_parser *p) {
   // strtol() and friends unfortunately do not support specifying the length of
   // the input string, so we need to force a copy into a NULL-terminated buffer.
   if (!multipart_text(p, "\0", 1, false)) {
@@ -9155,8 +9547,8 @@
   size_t len;
   const char *buf = accumulate_getptr(p, &len);
   const char *myend = buf + len - 1;  // One for NULL.
-  char *end;
 
+  char *end;
   switch (upb_fielddef_type(p->top->f)) {
     case UPB_TYPE_ENUM:
     case UPB_TYPE_INT32: {
@@ -9212,6 +9604,7 @@
   }
 
   multipart_end(p);
+
   return true;
 
 err:
@@ -9230,6 +9623,7 @@
 
   bool ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
   UPB_ASSERT_VAR(ok, ok);
+
   return true;
 }
 
@@ -9246,6 +9640,8 @@
     upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
     inner->m = p->top->m;
     inner->f = p->top->f;
+    inner->is_map = false;
+    inner->is_mapentry = false;
     p->top = inner;
 
     if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
@@ -9323,6 +9719,7 @@
   }
 
   multipart_end(p);
+
   return ok;
 }
 
@@ -9331,54 +9728,217 @@
   multipart_startaccum(p);
 }
 
-static bool end_member(upb_json_parser *p) {
-  assert(!p->top->f);
+// Helper: invoked during parse_mapentry() to emit the mapentry message's key
+// field based on the current contents of the accumulate buffer.
+static bool parse_mapentry_key(upb_json_parser *p) {
+
   size_t len;
   const char *buf = accumulate_getptr(p, &len);
 
-  const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len);
+  // Emit the key field. We do a bit of ad-hoc parsing here because the
+  // parser state machine has already decided that this is a string field
+  // name, and we are reinterpreting it as some arbitrary key type. In
+  // particular, integer and bool keys are quoted, so we need to parse the
+  // quoted string contents here.
 
-  if (!f) {
-    // TODO(haberman): Ignore unknown fields if requested/configured to do so.
-    upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
+  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
+  if (p->top->f == NULL) {
+    upb_status_seterrmsg(p->status, "mapentry message has no key");
     return false;
   }
-
-  p->top->f = f;
-  multipart_end(p);
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      // Invoke end_number. The accum buffer has the number's text already.
+      if (!parse_number(p)) {
+        return false;
+      }
+      break;
+    case UPB_TYPE_BOOL:
+      if (len == 4 && !strncmp(buf, "true", 4)) {
+        if (!parser_putbool(p, true)) {
+          return false;
+        }
+      } else if (len == 5 && !strncmp(buf, "false", 5)) {
+        if (!parser_putbool(p, false)) {
+          return false;
+        }
+      } else {
+        upb_status_seterrmsg(p->status,
+                             "Map bool key not 'true' or 'false'");
+        return false;
+      }
+      multipart_end(p);
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      upb_sink subsink;
+      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+      upb_sink_startstr(&p->top->sink, sel, len, &subsink);
+      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
+      upb_sink_putstring(&subsink, sel, buf, len, NULL);
+      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
+      upb_sink_endstr(&subsink, sel);
+      multipart_end(p);
+      break;
+    }
+    default:
+      upb_status_seterrmsg(p->status, "Invalid field type for map key");
+      return false;
+  }
 
   return true;
 }
 
-static void clear_member(upb_json_parser *p) { p->top->f = NULL; }
+// Helper: emit one map entry (as a submessage in the map field sequence). This
+// is invoked from end_membername(), at the end of the map entry's key string,
+// with the map key in the accumulate buffer. It parses the key from that
+// buffer, emits the handler calls to start the mapentry submessage (setting up
+// its subframe in the process), and sets up state in the subframe so that the
+// value parser (invoked next) will emit the mapentry's value field and then
+// end the mapentry message.
+
+static bool handle_mapentry(upb_json_parser *p) {
+  // Map entry: p->top->sink is the seq frame, so we need to start a frame
+  // for the mapentry itself, and then set |f| in that frame so that the map
+  // value field is parsed, and also set a flag to end the frame after the
+  // map-entry value is parsed.
+  if (!check_stack(p)) return false;
+
+  const upb_fielddef *mapfield = p->top->mapfield;
+  const upb_msgdef *mapentrymsg = upb_fielddef_msgsubdef(mapfield);
+
+  upb_jsonparser_frame *inner = p->top + 1;
+  p->top->f = mapfield;
+  upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+  upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+  inner->m = mapentrymsg;
+  inner->mapfield = mapfield;
+  inner->is_map = false;
+
+  // Don't set this to true *yet* -- we reuse parsing handlers below to push
+  // the key field value to the sink, and these handlers will pop the frame
+  // if they see is_mapentry (when invoked by the parser state machine, they
+  // would have just seen the map-entry value, not key).
+  inner->is_mapentry = false;
+  p->top = inner;
+
+  // send STARTMSG in submsg frame.
+  upb_sink_startmsg(&p->top->sink);
+
+  parse_mapentry_key(p);
+
+  // Set up the value field to receive the map-entry value.
+  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
+  p->top->is_mapentry = true;  // set up to pop frame after value is parsed.
+  p->top->mapfield = mapfield;
+  if (p->top->f == NULL) {
+    upb_status_seterrmsg(p->status, "mapentry message has no value");
+    return false;
+  }
+
+  return true;
+}
+
+static bool end_membername(upb_json_parser *p) {
+  assert(!p->top->f);
+
+  if (p->top->is_map) {
+    return handle_mapentry(p);
+  } else {
+    size_t len;
+    const char *buf = accumulate_getptr(p, &len);
+    const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len);
+
+    if (!f) {
+      // TODO(haberman): Ignore unknown fields if requested/configured to do so.
+      upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
+      return false;
+    }
+
+    p->top->f = f;
+    multipart_end(p);
+
+    return true;
+  }
+}
+
+static void end_member(upb_json_parser *p) {
+  // If we just parsed a map-entry value, end that frame too.
+  if (p->top->is_mapentry) {
+    assert(p->top > p->stack);
+    // send ENDMSG on submsg.
+    upb_status s = UPB_STATUS_INIT;
+    upb_sink_endmsg(&p->top->sink, &s);
+    const upb_fielddef* mapfield = p->top->mapfield;
+
+    // send ENDSUBMSG in repeated-field-of-mapentries frame.
+    p->top--;
+    upb_selector_t sel;
+    bool ok = upb_handlers_getselector(mapfield,
+                                       UPB_HANDLER_ENDSUBMSG, &sel);
+    UPB_ASSERT_VAR(ok, ok);
+    upb_sink_endsubmsg(&p->top->sink, sel);
+  }
+
+  p->top->f = NULL;
+}
 
 static bool start_subobject(upb_json_parser *p) {
   assert(p->top->f);
 
-  if (!upb_fielddef_issubmsg(p->top->f)) {
+  if (upb_fielddef_ismap(p->top->f)) {
+    // Beginning of a map. Start a new parser frame in a repeated-field
+    // context.
+    if (!check_stack(p)) return false;
+
+    upb_jsonparser_frame *inner = p->top + 1;
+    upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+    upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+    inner->m = upb_fielddef_msgsubdef(p->top->f);
+    inner->mapfield = p->top->f;
+    inner->f = NULL;
+    inner->is_map = true;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    return true;
+  } else if (upb_fielddef_issubmsg(p->top->f)) {
+    // Beginning of a subobject. Start a new parser frame in the submsg
+    // context.
+    if (!check_stack(p)) return false;
+
+    upb_jsonparser_frame *inner = p->top + 1;
+
+    upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+    upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+    inner->m = upb_fielddef_msgsubdef(p->top->f);
+    inner->f = NULL;
+    inner->is_map = false;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    return true;
+  } else {
     upb_status_seterrf(p->status,
                        "Object specified for non-message/group field: %s",
                        upb_fielddef_name(p->top->f));
     return false;
   }
-
-  if (!check_stack(p)) return false;
-
-  upb_jsonparser_frame *inner = p->top + 1;
-
-  upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-  upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
-  inner->m = upb_fielddef_msgsubdef(p->top->f);
-  inner->f = NULL;
-  p->top = inner;
-
-  return true;
 }
 
 static void end_subobject(upb_json_parser *p) {
-  p->top--;
-  upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
-  upb_sink_endsubmsg(&p->top->sink, sel);
+  if (p->top->is_map) {
+    p->top--;
+    upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+    upb_sink_endseq(&p->top->sink, sel);
+  } else {
+    p->top--;
+    upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
+    upb_sink_endsubmsg(&p->top->sink, sel);
+  }
 }
 
 static bool start_array(upb_json_parser *p) {
@@ -9398,6 +9958,8 @@
   upb_sink_startseq(&p->top->sink, sel, &inner->sink);
   inner->m = p->top->m;
   inner->f = p->top->f;
+  inner->is_map = false;
+  inner->is_mapentry = false;
   p->top = inner;
 
   return true;
@@ -9412,12 +9974,16 @@
 }
 
 static void start_object(upb_json_parser *p) {
-  upb_sink_startmsg(&p->top->sink);
+  if (!p->top->is_map) {
+    upb_sink_startmsg(&p->top->sink);
+  }
 }
 
 static void end_object(upb_json_parser *p) {
-  upb_status status;
-  upb_sink_endmsg(&p->top->sink, &status);
+  if (!p->top->is_map) {
+    upb_status status;
+    upb_sink_endmsg(&p->top->sink, &status);
+  }
 }
 
 
@@ -9442,11 +10008,11 @@
 // final state once, when the closing '"' is seen.
 
 
-#line 904 "upb/json/parser.rl"
+#line 1085 "upb/json/parser.rl"
 
 
 
-#line 816 "upb/json/parser.c"
+#line 997 "upb/json/parser.c"
 static const char _json_actions[] = {
 	0, 1, 0, 1, 2, 1, 3, 1, 
 	5, 1, 6, 1, 7, 1, 8, 1, 
@@ -9597,7 +10163,7 @@
 static const int json_en_main = 1;
 
 
-#line 907 "upb/json/parser.rl"
+#line 1088 "upb/json/parser.rl"
 
 size_t parse(void *closure, const void *hd, const char *buf, size_t size,
              const upb_bufhandle *handle) {
@@ -9617,7 +10183,7 @@
   capture_resume(parser, buf);
 
   
-#line 987 "upb/json/parser.c"
+#line 1168 "upb/json/parser.c"
 	{
 	int _klen;
 	unsigned int _trans;
@@ -9692,118 +10258,118 @@
 		switch ( *_acts++ )
 		{
 	case 0:
-#line 819 "upb/json/parser.rl"
+#line 1000 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 1:
-#line 820 "upb/json/parser.rl"
+#line 1001 "upb/json/parser.rl"
 	{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
 	break;
 	case 2:
-#line 824 "upb/json/parser.rl"
+#line 1005 "upb/json/parser.rl"
 	{ start_text(parser, p); }
 	break;
 	case 3:
-#line 825 "upb/json/parser.rl"
+#line 1006 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_text(parser, p)); }
 	break;
 	case 4:
-#line 831 "upb/json/parser.rl"
+#line 1012 "upb/json/parser.rl"
 	{ start_hex(parser); }
 	break;
 	case 5:
-#line 832 "upb/json/parser.rl"
+#line 1013 "upb/json/parser.rl"
 	{ hexdigit(parser, p); }
 	break;
 	case 6:
-#line 833 "upb/json/parser.rl"
+#line 1014 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_hex(parser)); }
 	break;
 	case 7:
-#line 839 "upb/json/parser.rl"
+#line 1020 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(escape(parser, p)); }
 	break;
 	case 8:
-#line 845 "upb/json/parser.rl"
+#line 1026 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 9:
-#line 848 "upb/json/parser.rl"
+#line 1029 "upb/json/parser.rl"
 	{ {stack[top++] = cs; cs = 19; goto _again;} }
 	break;
 	case 10:
-#line 850 "upb/json/parser.rl"
+#line 1031 "upb/json/parser.rl"
 	{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
 	break;
 	case 11:
-#line 855 "upb/json/parser.rl"
+#line 1036 "upb/json/parser.rl"
 	{ start_member(parser); }
 	break;
 	case 12:
-#line 856 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_member(parser)); }
+#line 1037 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_membername(parser)); }
 	break;
 	case 13:
-#line 859 "upb/json/parser.rl"
-	{ clear_member(parser); }
+#line 1040 "upb/json/parser.rl"
+	{ end_member(parser); }
 	break;
 	case 14:
-#line 865 "upb/json/parser.rl"
+#line 1046 "upb/json/parser.rl"
 	{ start_object(parser); }
 	break;
 	case 15:
-#line 868 "upb/json/parser.rl"
+#line 1049 "upb/json/parser.rl"
 	{ end_object(parser); }
 	break;
 	case 16:
-#line 874 "upb/json/parser.rl"
+#line 1055 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_array(parser)); }
 	break;
 	case 17:
-#line 878 "upb/json/parser.rl"
+#line 1059 "upb/json/parser.rl"
 	{ end_array(parser); }
 	break;
 	case 18:
-#line 883 "upb/json/parser.rl"
+#line 1064 "upb/json/parser.rl"
 	{ start_number(parser, p); }
 	break;
 	case 19:
-#line 884 "upb/json/parser.rl"
+#line 1065 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_number(parser, p)); }
 	break;
 	case 20:
-#line 886 "upb/json/parser.rl"
+#line 1067 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_stringval(parser)); }
 	break;
 	case 21:
-#line 887 "upb/json/parser.rl"
+#line 1068 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_stringval(parser)); }
 	break;
 	case 22:
-#line 889 "upb/json/parser.rl"
+#line 1070 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
 	break;
 	case 23:
-#line 891 "upb/json/parser.rl"
+#line 1072 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
 	break;
 	case 24:
-#line 893 "upb/json/parser.rl"
+#line 1074 "upb/json/parser.rl"
 	{ /* null value */ }
 	break;
 	case 25:
-#line 895 "upb/json/parser.rl"
+#line 1076 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_subobject(parser)); }
 	break;
 	case 26:
-#line 896 "upb/json/parser.rl"
+#line 1077 "upb/json/parser.rl"
 	{ end_subobject(parser); }
 	break;
 	case 27:
-#line 901 "upb/json/parser.rl"
+#line 1082 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
-#line 1173 "upb/json/parser.c"
+#line 1354 "upb/json/parser.c"
 		}
 	}
 
@@ -9816,7 +10382,7 @@
 	_out: {}
 	}
 
-#line 926 "upb/json/parser.rl"
+#line 1107 "upb/json/parser.rl"
 
   if (p != pe) {
     upb_status_seterrf(parser->status, "Parse error at %s\n", p);
@@ -9860,18 +10426,20 @@
 void upb_json_parser_reset(upb_json_parser *p) {
   p->top = p->stack;
   p->top->f = NULL;
+  p->top->is_map = false;
+  p->top->is_mapentry = false;
 
   int cs;
   int top;
   // Emit Ragel initialization of the parser.
   
-#line 1235 "upb/json/parser.c"
+#line 1418 "upb/json/parser.c"
 	{
 	cs = json_start;
 	top = 0;
 	}
 
-#line 974 "upb/json/parser.rl"
+#line 1157 "upb/json/parser.rl"
   p->current_state = cs;
   p->parser_top = top;
   accumulate_clear(p);
@@ -10072,13 +10640,23 @@
     return true;                                                             \
   }                                                                          \
   static bool repeated_##type(void *closure, const void *handler_data,       \
-                            type val) {                                      \
+                              type val) {                                    \
     upb_json_printer *p = closure;                                           \
     print_comma(p);                                                          \
     CHK(put##type(closure, handler_data, val));                              \
     return true;                                                             \
   }
 
+#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
+  static bool putmapkey_##type(void *closure, const void *handler_data,      \
+                            type val) {                                      \
+    upb_json_printer *p = closure;                                           \
+    print_data(p, "\"", 1);                                                  \
+    CHK(put##type(closure, handler_data, val));                              \
+    print_data(p, "\":", 2);                                                 \
+    return true;                                                             \
+  }
+
 TYPE_HANDLERS(double,   fmt_double);
 TYPE_HANDLERS(float,    fmt_float);
 TYPE_HANDLERS(bool,     fmt_bool);
@@ -10087,7 +10665,15 @@
 TYPE_HANDLERS(int64_t,  fmt_int64);
 TYPE_HANDLERS(uint64_t, fmt_uint64);
 
+// double and float are not allowed to be map keys.
+TYPE_HANDLERS_MAPKEY(bool,     fmt_bool);
+TYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64);
+TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64);
+TYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64);
+TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64);
+
 #undef TYPE_HANDLERS
+#undef TYPE_HANDLERS_MAPKEY
 
 typedef struct {
   void *keyname;
@@ -10112,20 +10698,36 @@
   return true;
 }
 
+static void print_enum_symbolic_name(upb_json_printer *p,
+                                     const upb_enumdef *def,
+                                     int32_t val) {
+  const char *symbolic_name = upb_enumdef_iton(def, val);
+  if (symbolic_name) {
+    print_data(p, "\"", 1);
+    putstring(p, symbolic_name, strlen(symbolic_name));
+    print_data(p, "\"", 1);
+  } else {
+    putint32_t(p, NULL, val);
+  }
+}
+
 static bool repeated_enum(void *closure, const void *handler_data,
                           int32_t val) {
   const EnumHandlerData *hd = handler_data;
   upb_json_printer *p = closure;
   print_comma(p);
 
-  const char *symbolic_name = upb_enumdef_iton(hd->enumdef, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(closure, NULL, val);
-  }
+  print_enum_symbolic_name(p, hd->enumdef, val);
+
+  return true;
+}
+
+static bool mapvalue_enum(void *closure, const void *handler_data,
+                          int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+
+  print_enum_symbolic_name(p, hd->enumdef, val);
 
   return true;
 }
@@ -10141,25 +10743,35 @@
   return closure;
 }
 
-static bool startmap(void *closure, const void *handler_data) {
-  UPB_UNUSED(handler_data);
-  upb_json_printer *p = closure;
-  if (p->depth_++ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
+static void start_frame(upb_json_printer *p) {
+  p->depth_++;
   p->first_elem_[p->depth_] = true;
   print_data(p, "{", 1);
+}
+
+static void end_frame(upb_json_printer *p) {
+  print_data(p, "}", 1);
+  p->depth_--;
+}
+
+static bool printer_startmsg(void *closure, const void *handler_data) {
+  UPB_UNUSED(handler_data);
+  upb_json_printer *p = closure;
+  if (p->depth_ == 0) {
+    upb_bytessink_start(p->output_, 0, &p->subc_);
+  }
+  start_frame(p);
   return true;
 }
 
-static bool endmap(void *closure, const void *handler_data, upb_status *s) {
+static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
   UPB_UNUSED(handler_data);
   UPB_UNUSED(s);
   upb_json_printer *p = closure;
-  if (--p->depth_ == 0) {
+  end_frame(p);
+  if (p->depth_ == 0) {
     upb_bytessink_end(p->output_);
   }
-  print_data(p, "}", 1);
   return true;
 }
 
@@ -10180,6 +10792,23 @@
   return true;
 }
 
+static void *startmap(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  CHK(putkey(closure, handler_data));
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "{", 1);
+  return closure;
+}
+
+static bool endmap(void *closure, const void *handler_data) {
+  UPB_UNUSED(handler_data);
+  upb_json_printer *p = closure;
+  print_data(p, "}", 1);
+  p->depth_--;
+  return true;
+}
+
 static size_t putstr(void *closure, const void *handler_data, const char *str,
                      size_t len, const upb_bufhandle *handle) {
   UPB_UNUSED(handler_data);
@@ -10294,6 +10923,36 @@
   return true;
 }
 
+static void *mapkeyval_startstr(void *closure, const void *handler_data,
+                                size_t size_hint) {
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  upb_json_printer *p = closure;
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t mapkey_str(void *closure, const void *handler_data,
+                         const char *str, size_t len,
+                         const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool mapkey_endstr(void *closure, const void *handler_data) {
+  UPB_UNUSED(handler_data);
+  upb_json_printer *p = closure;
+  print_data(p, "\":", 2);
+  return true;
+}
+
+static bool mapvalue_endstr(void *closure, const void *handler_data) {
+  UPB_UNUSED(handler_data);
+  upb_json_printer *p = closure;
+  print_data(p, "\"", 1);
+  return true;
+}
+
 static size_t scalar_bytes(void *closure, const void *handler_data,
                            const char *str, size_t len,
                            const upb_bufhandle *handle) {
@@ -10311,31 +10970,161 @@
   return len;
 }
 
-void printer_sethandlers(const void *closure, upb_handlers *h) {
+static size_t mapkey_bytes(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  print_data(p, ":", 1);
+  return len;
+}
+
+static void set_enum_hd(upb_handlers *h,
+                        const upb_fielddef *f,
+                        upb_handlerattr *attr) {
+  EnumHandlerData *hd = malloc(sizeof(EnumHandlerData));
+  hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
+  hd->keyname = newstrpc(h, f);
+  upb_handlers_addcleanup(h, hd, free);
+  upb_handlerattr_sethandlerdata(attr, hd);
+}
+
+// Set up handlers for a mapentry submessage (i.e., an individual key/value pair
+// in a map).
+//
+// TODO: Handle missing key, missing value, out-of-order key/value, or repeated
+// key or value cases properly. The right way to do this is to allocate a
+// temporary structure at the start of a mapentry submessage, store key and
+// value data in it as key and value handlers are called, and then print the
+// key/value pair once at the end of the submessage. If we don't do this, we
+// should at least detect the case and throw an error. However, so far all of
+// our sources that emit mapentry messages do so canonically (with one key
+// field, and then one value field), so this is not a pressing concern at the
+// moment.
+void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
   UPB_UNUSED(closure);
+  const upb_msgdef *md = upb_handlers_msgdef(h);
+
+  // A mapentry message is printed simply as '"key": value'. Rather than
+  // special-case key and value for every type below, we just handle both
+  // fields explicitly here.
+  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
+  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
 
   upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
-  upb_handlers_setstartmsg(h, startmap, &empty_attr);
-  upb_handlers_setendmsg(h, endmap, &empty_attr);
 
-#define TYPE(type, name, ctype)                                    \
-  case type:                                                       \
-    if (upb_fielddef_isseq(f)) {                                   \
-      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr); \
-    } else {                                                       \
-      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);    \
-    }                                                              \
+  switch (upb_fielddef_type(key_field)) {
+    case UPB_TYPE_INT32:
+      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
+      break;
+    case UPB_TYPE_INT64:
+      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT32:
+      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT64:
+      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_BOOL:
+      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
+      break;
+    case UPB_TYPE_STRING:
+      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
+      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
+      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
+      break;
+    case UPB_TYPE_BYTES:
+      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
+      break;
+    default:
+      assert(false);
+      break;
+  }
+
+  switch (upb_fielddef_type(value_field)) {
+    case UPB_TYPE_INT32:
+      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_INT64:
+      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT32:
+      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT64:
+      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_BOOL:
+      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
+      break;
+    case UPB_TYPE_FLOAT:
+      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
+      break;
+    case UPB_TYPE_DOUBLE:
+      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
+      break;
+    case UPB_TYPE_STRING:
+      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
+      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
+      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
+      break;
+    case UPB_TYPE_BYTES:
+      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
+      break;
+    case UPB_TYPE_ENUM: {
+      upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+      set_enum_hd(h, value_field, &enum_attr);
+      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
+      upb_handlerattr_uninit(&enum_attr);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      // No handler necessary -- the submsg handlers will print the message
+      // as appropriate.
+      break;
+  }
+
+  upb_handlerattr_uninit(&empty_attr);
+}
+
+void printer_sethandlers(const void *closure, upb_handlers *h) {
+  UPB_UNUSED(closure);
+  const upb_msgdef *md = upb_handlers_msgdef(h);
+  bool is_mapentry = upb_msgdef_mapentry(md);
+  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+
+  if (is_mapentry) {
+    // mapentry messages are sufficiently different that we handle them
+    // separately.
+    printer_sethandlers_mapentry(closure, h);
+    return;
+  }
+
+  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
+  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
+
+#define TYPE(type, name, ctype)                                               \
+  case type:                                                                  \
+    if (upb_fielddef_isseq(f)) {                                              \
+      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
+    } else {                                                                  \
+      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
+    }                                                                         \
     break;
 
-  upb_msg_iter i;
-  upb_msg_begin(&i, upb_handlers_msgdef(h));
-  for(; !upb_msg_done(&i); upb_msg_next(&i)) {
+  upb_msg_field_iter i;
+  upb_msg_field_begin(&i, md);
+  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
     const upb_fielddef *f = upb_msg_iter_field(&i);
 
     upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
     upb_handlerattr_sethandlerdata(&name_attr, newstrpc(h, f));
 
-    if (upb_fielddef_isseq(f)) {
+    if (upb_fielddef_ismap(f)) {
+      upb_handlers_setstartseq(h, f, startmap, &name_attr);
+      upb_handlers_setendseq(h, f, endmap, &name_attr);
+    } else if (upb_fielddef_isseq(f)) {
       upb_handlers_setstartseq(h, f, startseq, &name_attr);
       upb_handlers_setendseq(h, f, endseq, &empty_attr);
     }
@@ -10352,12 +11141,8 @@
         // For now, we always emit symbolic names for enums. We may want an
         // option later to control this behavior, but we will wait for a real
         // need first.
-        EnumHandlerData *hd = malloc(sizeof(EnumHandlerData));
-        hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
-        hd->keyname = newstrpc(h, f);
-        upb_handlers_addcleanup(h, hd, free);
         upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
-        upb_handlerattr_sethandlerdata(&enum_attr, hd);
+        set_enum_hd(h, f, &enum_attr);
 
         if (upb_fielddef_isseq(f)) {
           upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h
index fbcb8e9..8f6d364 100644
--- a/ruby/ext/google/protobuf_c/upb.h
+++ b/ruby/ext/google/protobuf_c/upb.h
@@ -710,6 +710,9 @@
 #define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \
   {{count, mask, ctype, size_lg2, entries}}
 
+#define UPB_EMPTY_STRTABLE_INIT(ctype)                           \
+  UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL)
+
 typedef struct {
   upb_table t;              // For entries that don't fit in the array part.
   const _upb_value *array;  // Array part of the table.  See const note above.
@@ -1129,6 +1132,7 @@
 class EnumDef;
 class FieldDef;
 class MessageDef;
+class OneofDef;
 }
 #endif
 
@@ -1136,6 +1140,7 @@
 UPB_DECLARE_TYPE(upb::EnumDef, upb_enumdef);
 UPB_DECLARE_TYPE(upb::FieldDef, upb_fielddef);
 UPB_DECLARE_TYPE(upb::MessageDef, upb_msgdef);
+UPB_DECLARE_TYPE(upb::OneofDef, upb_oneofdef);
 
 // Maximum field number allowed for FieldDefs.  This is an inherent limit of the
 // protobuf wire format.
@@ -1159,6 +1164,7 @@
   UPB_DEF_MSG,
   UPB_DEF_FIELD,
   UPB_DEF_ENUM,
+  UPB_DEF_ONEOF,
   UPB_DEF_SERVICE,   // Not yet implemented.
   UPB_DEF_ANY = -1,  // Wildcard for upb_symtab_get*()
 } upb_deftype_t;
@@ -1443,6 +1449,10 @@
   const MessageDef* containing_type() const;
   const char* containing_type_name();
 
+  // The OneofDef to which this field belongs, or NULL if this field is not part
+  // of a oneof.
+  const OneofDef* containing_oneof() const;
+
   // The field's type according to the enum in descriptor.proto.  This is not
   // the same as UPB_TYPE_*, because it distinguishes between (for example)
   // INT32 and SINT32, whereas our "type" enum does not.  This return of
@@ -1456,6 +1466,7 @@
   bool IsString() const;
   bool IsSequence() const;
   bool IsPrimitive() const;
+  bool IsMap() const;
 
   // How integers are encoded.  Only meaningful for integer types.
   // Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes.
@@ -1616,6 +1627,7 @@
   } sub;  // The msgdef or enumdef for this field, if upb_hassubdef(f).
   bool subdef_is_symbolic;
   bool msg_is_symbolic;
+  const upb_oneofdef *oneof;
   bool default_is_string;
   bool type_is_set_;     // False until type is explicitly set.
   bool is_extension_;
@@ -1631,11 +1643,11 @@
 ));
 
 #define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy,   \
-                          packed, name, num, msgdef, subdef, selector_base,     \
+                          packed, name, num, msgdef, subdef, selector_base,    \
                           index, defaultval, refs, ref2s)                      \
   {                                                                            \
     UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef},      \
-        {subdef}, false, false,                                                \
+        {subdef}, NULL, false, false,                                          \
         type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \
         lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \
   }
@@ -1669,6 +1681,7 @@
 bool upb_fielddef_lazy(const upb_fielddef *f);
 bool upb_fielddef_packed(const upb_fielddef *f);
 const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
 upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f);
 const char *upb_fielddef_containingtypename(upb_fielddef *f);
 upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f);
@@ -1678,6 +1691,7 @@
 bool upb_fielddef_isstring(const upb_fielddef *f);
 bool upb_fielddef_isseq(const upb_fielddef *f);
 bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
 int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
 int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
 uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
@@ -1736,7 +1750,8 @@
 
 /* upb::MessageDef ************************************************************/
 
-typedef upb_inttable_iter upb_msg_iter;
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
 
 // Structure that describes a single .proto message type.
 //
@@ -1766,14 +1781,37 @@
   // The number of fields that belong to the MessageDef.
   int field_count() const;
 
+  // The number of oneofs that belong to the MessageDef.
+  int oneof_count() const;
+
   // Adds a field (upb_fielddef object) to a msgdef.  Requires that the msgdef
   // and the fielddefs are mutable.  The fielddef's name and number must be
   // set, and the message may not already contain any field with this name or
   // number, and this fielddef may not be part of another message.  In error
   // cases false is returned and the msgdef is unchanged.
+  //
+  // If the given field is part of a oneof, this call succeeds if and only if
+  // that oneof is already part of this msgdef. (Note that adding a oneof to a
+  // msgdef automatically adds all of its fields to the msgdef at the time that
+  // the oneof is added, so it is usually more idiomatic to add the oneof's
+  // fields first then add the oneof to the msgdef. This case is supported for
+  // convenience.)
+  //
+  // If |f| is already part of this MessageDef, this method performs no action
+  // and returns true (success). Thus, this method is idempotent.
   bool AddField(FieldDef* f, Status* s);
   bool AddField(const reffed_ptr<FieldDef>& f, Status* s);
 
+  // Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef,
+  // oneof, and any fielddefs are mutable, that the fielddefs contained in the
+  // oneof do not have any name or number conflicts with existing fields in the
+  // msgdef, and that the oneof's name is unique among all oneofs in the msgdef.
+  // If the oneof is added successfully, all of its fields will be added
+  // directly to the msgdef as well. In error cases, false is returned and the
+  // msgdef is unchanged.
+  bool AddOneof(OneofDef* o, Status* s);
+  bool AddOneof(const reffed_ptr<OneofDef>& o, Status* s);
+
   // These return NULL if the field is not found.
   FieldDef* FindFieldByNumber(uint32_t number);
   FieldDef* FindFieldByName(const char *name, size_t len);
@@ -1797,6 +1835,25 @@
     return FindFieldByName(str.c_str(), str.size());
   }
 
+  OneofDef* FindOneofByName(const char* name, size_t len);
+  const OneofDef* FindOneofByName(const char* name, size_t len) const;
+
+  OneofDef* FindOneofByName(const char* name) {
+    return FindOneofByName(name, strlen(name));
+  }
+  const OneofDef* FindOneofByName(const char* name) const {
+    return FindOneofByName(name, strlen(name));
+  }
+
+  template<class T>
+  OneofDef* FindOneofByName(const T& str) {
+    return FindOneofByName(str.c_str(), str.size());
+  }
+  template<class T>
+  const OneofDef* FindOneofByName(const T& str) const {
+    return FindOneofByName(str.c_str(), str.size());
+  }
+
   // Returns a new msgdef that is a copy of the given msgdef (and a copy of all
   // the fields) but with any references to submessages broken and replaced
   // with just the name of the submessage.  Returns NULL if memory allocation
@@ -1812,39 +1869,117 @@
   bool mapentry() const;
 
   // Iteration over fields.  The order is undefined.
-  class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+  class field_iterator
+      : public std::iterator<std::forward_iterator_tag, FieldDef*> {
    public:
-    explicit iterator(MessageDef* md);
-    static iterator end(MessageDef* md);
+    explicit field_iterator(MessageDef* md);
+    static field_iterator end(MessageDef* md);
 
     void operator++();
     FieldDef* operator*() const;
-    bool operator!=(const iterator& other) const;
-    bool operator==(const iterator& other) const;
+    bool operator!=(const field_iterator& other) const;
+    bool operator==(const field_iterator& other) const;
 
    private:
-    upb_msg_iter iter_;
+    upb_msg_field_iter iter_;
   };
 
-  class const_iterator
+  class const_field_iterator
       : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
    public:
-    explicit const_iterator(const MessageDef* md);
-    static const_iterator end(const MessageDef* md);
+    explicit const_field_iterator(const MessageDef* md);
+    static const_field_iterator end(const MessageDef* md);
 
     void operator++();
     const FieldDef* operator*() const;
-    bool operator!=(const const_iterator& other) const;
-    bool operator==(const const_iterator& other) const;
+    bool operator!=(const const_field_iterator& other) const;
+    bool operator==(const const_field_iterator& other) const;
 
    private:
-    upb_msg_iter iter_;
+    upb_msg_field_iter iter_;
   };
 
-  iterator begin();
-  iterator end();
-  const_iterator begin() const;
-  const_iterator end() const;
+  // Iteration over oneofs. The order is undefined.
+  class oneof_iterator
+      : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit oneof_iterator(MessageDef* md);
+    static oneof_iterator end(MessageDef* md);
+
+    void operator++();
+    OneofDef* operator*() const;
+    bool operator!=(const oneof_iterator& other) const;
+    bool operator==(const oneof_iterator& other) const;
+
+   private:
+    upb_msg_oneof_iter iter_;
+  };
+
+  class const_oneof_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_oneof_iterator(const MessageDef* md);
+    static const_oneof_iterator end(const MessageDef* md);
+
+    void operator++();
+    const OneofDef* operator*() const;
+    bool operator!=(const const_oneof_iterator& other) const;
+    bool operator==(const const_oneof_iterator& other) const;
+
+   private:
+    upb_msg_oneof_iter iter_;
+  };
+
+  class FieldAccessor {
+   public:
+    explicit FieldAccessor(MessageDef* msg) : msg_(msg) {}
+    field_iterator begin() { return msg_->field_begin(); }
+    field_iterator end() { return msg_->field_end(); }
+   private:
+    MessageDef* msg_;
+  };
+
+  class ConstFieldAccessor {
+   public:
+    explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {}
+    const_field_iterator begin() { return msg_->field_begin(); }
+    const_field_iterator end() { return msg_->field_end(); }
+   private:
+    const MessageDef* msg_;
+  };
+
+  class OneofAccessor {
+   public:
+    explicit OneofAccessor(MessageDef* msg) : msg_(msg) {}
+    oneof_iterator begin() { return msg_->oneof_begin(); }
+    oneof_iterator end() { return msg_->oneof_end(); }
+   private:
+    MessageDef* msg_;
+  };
+
+  class ConstOneofAccessor {
+   public:
+    explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {}
+    const_oneof_iterator begin() { return msg_->oneof_begin(); }
+    const_oneof_iterator end() { return msg_->oneof_end(); }
+   private:
+    const MessageDef* msg_;
+  };
+
+  field_iterator field_begin();
+  field_iterator field_end();
+  const_field_iterator field_begin() const;
+  const_field_iterator field_end() const;
+
+  oneof_iterator oneof_begin();
+  oneof_iterator oneof_end();
+  const_oneof_iterator oneof_begin() const;
+  const_oneof_iterator oneof_end() const;
+
+  FieldAccessor fields() { return FieldAccessor(this); }
+  ConstFieldAccessor fields() const { return ConstFieldAccessor(this); }
+  OneofAccessor oneofs() { return OneofAccessor(this); }
+  ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); }
 
  private:
   UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef);
@@ -1857,6 +1992,9 @@
   upb_inttable itof;  // int to field
   upb_strtable ntof;  // name to field
 
+  // Tables for looking up oneofs by name.
+  upb_strtable ntoo;  // name to oneof
+
   // Is this a map-entry message?
   // TODO: set this flag properly for static descriptors; regenerate
   // descriptor.upb.c.
@@ -1865,11 +2003,14 @@
   // TODO(haberman): proper extension ranges (there can be multiple).
 ));
 
+// TODO: also support static initialization of the oneofs table. This will be
+// needed if we compile in descriptors that contain oneofs.
 #define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \
                         refs, ref2s)                                          \
   {                                                                           \
     UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count,             \
-        submsg_field_count, itof, ntof, false                                 \
+        submsg_field_count, itof, ntof,                                       \
+        UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false                         \
   }
 
 UPB_BEGIN_EXTERN_C  // {
@@ -1893,6 +2034,8 @@
 upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner);
 bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
                          upb_status *s);
+bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
+                         upb_status *s);
 
 // Field lookup in a couple of different variations:
 //   - itof = int to field
@@ -1917,11 +2060,38 @@
   return (upb_fielddef *)upb_msgdef_ntof(m, name, len);
 }
 
+// Oneof lookup:
+//   - ntoo = name to oneof
+//   - ntooz = name to oneof, null-terminated string.
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+                                               const char *name) {
+  return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m,
+                                                 const char *name, size_t len) {
+  return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len);
+}
+
 void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
 bool upb_msgdef_mapentry(const upb_msgdef *m);
 
-// upb_msg_iter i;
-// for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+// Well-known field tag numbers for map-entry messages.
+#define UPB_MAPENTRY_KEY   1
+#define UPB_MAPENTRY_VALUE 2
+
+const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m,
+                                          const char *name);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+
+// upb_msg_field_iter i;
+// for(upb_msg_field_begin(&i, m);
+//     !upb_msg_field_done(&i);
+//     upb_msg_field_next(&i)) {
 //   upb_fielddef *f = upb_msg_iter_field(&i);
 //   // ...
 // }
@@ -1929,11 +2099,18 @@
 // For C we don't have separate iterators for const and non-const.
 // It is the caller's responsibility to cast the upb_fielddef* to
 // const if the upb_msgdef* is const.
-void upb_msg_begin(upb_msg_iter *iter, const upb_msgdef *m);
-void upb_msg_next(upb_msg_iter *iter);
-bool upb_msg_done(const upb_msg_iter *iter);
-upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter);
-void upb_msg_iter_setdone(upb_msg_iter *iter);
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+
+// Similar to above, we also support iterating through the oneofs in a msgdef.
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter);
 
 UPB_END_EXTERN_C  // }
 
@@ -2075,6 +2252,172 @@
 
 UPB_END_EXTERN_C  // }
 
+/* upb::OneofDef **************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+// Class that represents a oneof.  Its base class is upb::Def (convert with
+// upb::upcast()).
+UPB_DEFINE_DEF(upb::OneofDef, oneofdef, ONEOF, UPB_QUOTE(
+ public:
+  // Returns NULL if memory allocation failed.
+  static reffed_ptr<OneofDef> New();
+
+  // Functionality from upb::RefCounted.
+  bool IsFrozen() const;
+  void Ref(const void* owner) const;
+  void Unref(const void* owner) const;
+  void DonateRef(const void* from, const void* to) const;
+  void CheckRef(const void* owner) const;
+
+  // Functionality from upb::Def.
+  const char* full_name() const;
+
+  // Returns the MessageDef that owns this OneofDef.
+  const MessageDef* containing_type() const;
+
+  // Returns the name of this oneof. This is the name used to look up the oneof
+  // by name once added to a message def.
+  const char* name() const;
+  bool set_name(const char* name, Status* s);
+
+  // Returns the number of fields currently defined in the oneof.
+  int field_count() const;
+
+  // Adds a field to the oneof. The field must not have been added to any other
+  // oneof or msgdef. If the oneof is not yet part of a msgdef, then when the
+  // oneof is eventually added to a msgdef, all fields added to the oneof will
+  // also be added to the msgdef at that time. If the oneof is already part of a
+  // msgdef, the field must either be a part of that msgdef already, or must not
+  // be a part of any msgdef; in the latter case, the field is added to the
+  // msgdef as a part of this operation.
+  //
+  // The field may only have an OPTIONAL label, never REQUIRED or REPEATED.
+  //
+  // If |f| is already part of this MessageDef, this method performs no action
+  // and returns true (success). Thus, this method is idempotent.
+  bool AddField(FieldDef* field, Status* s);
+  bool AddField(const reffed_ptr<FieldDef>& field, Status* s);
+
+  // Looks up by name.
+  const FieldDef* FindFieldByName(const char* name, size_t len) const;
+  FieldDef* FindFieldByName(const char* name, size_t len);
+  const FieldDef* FindFieldByName(const char* name) const {
+    return FindFieldByName(name, strlen(name));
+  }
+  FieldDef* FindFieldByName(const char* name) {
+    return FindFieldByName(name, strlen(name));
+  }
+
+  template <class T>
+  FieldDef* FindFieldByName(const T& str) {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+  template <class T>
+  const FieldDef* FindFieldByName(const T& str) const {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+
+  // Looks up by tag number.
+  const FieldDef* FindFieldByNumber(uint32_t num) const;
+
+  // Returns a new OneofDef with all the same fields. The OneofDef will be owned
+  // by the given owner.
+  OneofDef* Dup(const void* owner) const;
+
+  // Iteration over fields.  The order is undefined.
+  class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit iterator(OneofDef* md);
+    static iterator end(OneofDef* md);
+
+    void operator++();
+    FieldDef* operator*() const;
+    bool operator!=(const iterator& other) const;
+    bool operator==(const iterator& other) const;
+
+   private:
+    upb_oneof_iter iter_;
+  };
+
+  class const_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_iterator(const OneofDef* md);
+    static const_iterator end(const OneofDef* md);
+
+    void operator++();
+    const FieldDef* operator*() const;
+    bool operator!=(const const_iterator& other) const;
+    bool operator==(const const_iterator& other) const;
+
+   private:
+    upb_oneof_iter iter_;
+  };
+
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
+ private:
+  UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef);
+),
+UPB_DEFINE_STRUCT(upb_oneofdef, upb_def,
+  upb_strtable ntof;
+  upb_inttable itof;
+  const upb_msgdef *parent;
+));
+
+#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \
+  { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof }
+
+UPB_BEGIN_EXTERN_C  // {
+
+// Native C API.
+upb_oneofdef *upb_oneofdef_new(const void *owner);
+upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner);
+
+// From upb_refcounted.
+void upb_oneofdef_unref(const upb_oneofdef *o, const void *owner);
+bool upb_oneofdef_isfrozen(const upb_oneofdef *e);
+void upb_oneofdef_ref(const upb_oneofdef *o, const void *owner);
+void upb_oneofdef_donateref(const upb_oneofdef *m, const void *from,
+                           const void *to);
+void upb_oneofdef_checkref(const upb_oneofdef *o, const void *owner);
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s);
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
+                           const void *ref_donor,
+                           upb_status *s);
+
+// Oneof lookups:
+// - ntof:  look up a field by name.
+// - ntofz: look up a field by name (as a null-terminated string).
+// - itof:  look up a field by number.
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+                                                  const char *name) {
+  return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+//  upb_oneof_iter i;
+//  for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+//    // ...
+//  }
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+
+UPB_END_EXTERN_C  // }
 
 #ifdef __cplusplus
 
@@ -2201,6 +2544,9 @@
 inline const MessageDef* FieldDef::containing_type() const {
   return upb_fielddef_containingtype(this);
 }
+inline const OneofDef* FieldDef::containing_oneof() const {
+  return upb_fielddef_containingoneof(this);
+}
 inline const char* FieldDef::containing_type_name() {
   return upb_fielddef_containingtypename(this);
 }
@@ -2237,6 +2583,7 @@
 }
 inline bool FieldDef::IsString() const { return upb_fielddef_isstring(this); }
 inline bool FieldDef::IsSequence() const { return upb_fielddef_isseq(this); }
+inline bool FieldDef::IsMap() const { return upb_fielddef_ismap(this); }
 inline int64_t FieldDef::default_int64() const {
   return upb_fielddef_defaultint64(this);
 }
@@ -2351,12 +2698,21 @@
 inline int MessageDef::field_count() const {
   return upb_msgdef_numfields(this);
 }
+inline int MessageDef::oneof_count() const {
+  return upb_msgdef_numoneofs(this);
+}
 inline bool MessageDef::AddField(upb_fielddef* f, Status* s) {
   return upb_msgdef_addfield(this, f, NULL, s);
 }
 inline bool MessageDef::AddField(const reffed_ptr<FieldDef>& f, Status* s) {
   return upb_msgdef_addfield(this, f.get(), NULL, s);
 }
+inline bool MessageDef::AddOneof(upb_oneofdef* o, Status* s) {
+  return upb_msgdef_addoneof(this, o, NULL, s);
+}
+inline bool MessageDef::AddOneof(const reffed_ptr<OneofDef>& o, Status* s) {
+  return upb_msgdef_addoneof(this, o.get(), NULL, s);
+}
 inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) {
   return upb_msgdef_itof_mutable(this, number);
 }
@@ -2370,6 +2726,13 @@
                                                    size_t len) const {
   return upb_msgdef_ntof(this, name, len);
 }
+inline OneofDef* MessageDef::FindOneofByName(const char* name, size_t len) {
+  return upb_msgdef_ntoo_mutable(this, name, len);
+}
+inline const OneofDef* MessageDef::FindOneofByName(const char* name,
+                                                   size_t len) const {
+  return upb_msgdef_ntoo(this, name, len);
+}
 inline MessageDef* MessageDef::Dup(const void *owner) const {
   return upb_msgdef_dup(this, owner);
 }
@@ -2379,55 +2742,127 @@
 inline bool MessageDef::mapentry() const {
   return upb_msgdef_mapentry(this);
 }
-inline MessageDef::iterator MessageDef::begin() { return iterator(this); }
-inline MessageDef::iterator MessageDef::end() { return iterator::end(this); }
-inline MessageDef::const_iterator MessageDef::begin() const {
-  return const_iterator(this);
+inline MessageDef::field_iterator MessageDef::field_begin() {
+  return field_iterator(this);
 }
-inline MessageDef::const_iterator MessageDef::end() const {
-  return const_iterator::end(this);
+inline MessageDef::field_iterator MessageDef::field_end() {
+  return field_iterator::end(this);
+}
+inline MessageDef::const_field_iterator MessageDef::field_begin() const {
+  return const_field_iterator(this);
+}
+inline MessageDef::const_field_iterator MessageDef::field_end() const {
+  return const_field_iterator::end(this);
 }
 
-inline MessageDef::iterator::iterator(MessageDef* md) {
-  upb_msg_begin(&iter_, md);
+inline MessageDef::oneof_iterator MessageDef::oneof_begin() {
+  return oneof_iterator(this);
 }
-inline MessageDef::iterator MessageDef::iterator::end(MessageDef* md) {
-  MessageDef::iterator iter(md);
-  upb_msg_iter_setdone(&iter.iter_);
+inline MessageDef::oneof_iterator MessageDef::oneof_end() {
+  return oneof_iterator::end(this);
+}
+inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const {
+  return const_oneof_iterator(this);
+}
+inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const {
+  return const_oneof_iterator::end(this);
+}
+
+inline MessageDef::field_iterator::field_iterator(MessageDef* md) {
+  upb_msg_field_begin(&iter_, md);
+}
+inline MessageDef::field_iterator MessageDef::field_iterator::end(
+    MessageDef* md) {
+  MessageDef::field_iterator iter(md);
+  upb_msg_field_iter_setdone(&iter.iter_);
   return iter;
 }
-inline FieldDef* MessageDef::iterator::operator*() const {
+inline FieldDef* MessageDef::field_iterator::operator*() const {
   return upb_msg_iter_field(&iter_);
 }
-inline void MessageDef::iterator::operator++() { return upb_msg_next(&iter_); }
-inline bool MessageDef::iterator::operator==(const iterator &other) const {
+inline void MessageDef::field_iterator::operator++() {
+  return upb_msg_field_next(&iter_);
+}
+inline bool MessageDef::field_iterator::operator==(
+    const field_iterator &other) const {
   return upb_inttable_iter_isequal(&iter_, &other.iter_);
 }
-inline bool MessageDef::iterator::operator!=(const iterator &other) const {
+inline bool MessageDef::field_iterator::operator!=(
+    const field_iterator &other) const {
   return !(*this == other);
 }
 
-inline MessageDef::const_iterator::const_iterator(const MessageDef* md) {
-  upb_msg_begin(&iter_, md);
+inline MessageDef::const_field_iterator::const_field_iterator(
+    const MessageDef* md) {
+  upb_msg_field_begin(&iter_, md);
 }
-inline MessageDef::const_iterator MessageDef::const_iterator::end(
+inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end(
     const MessageDef *md) {
-  MessageDef::const_iterator iter(md);
-  upb_msg_iter_setdone(&iter.iter_);
+  MessageDef::const_field_iterator iter(md);
+  upb_msg_field_iter_setdone(&iter.iter_);
   return iter;
 }
-inline const FieldDef* MessageDef::const_iterator::operator*() const {
+inline const FieldDef* MessageDef::const_field_iterator::operator*() const {
   return upb_msg_iter_field(&iter_);
 }
-inline void MessageDef::const_iterator::operator++() {
-  return upb_msg_next(&iter_);
+inline void MessageDef::const_field_iterator::operator++() {
+  return upb_msg_field_next(&iter_);
 }
-inline bool MessageDef::const_iterator::operator==(
-    const const_iterator &other) const {
+inline bool MessageDef::const_field_iterator::operator==(
+    const const_field_iterator &other) const {
   return upb_inttable_iter_isequal(&iter_, &other.iter_);
 }
-inline bool MessageDef::const_iterator::operator!=(
-    const const_iterator &other) const {
+inline bool MessageDef::const_field_iterator::operator!=(
+    const const_field_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::oneof_iterator::oneof_iterator(MessageDef* md) {
+  upb_msg_oneof_begin(&iter_, md);
+}
+inline MessageDef::oneof_iterator MessageDef::oneof_iterator::end(
+    MessageDef* md) {
+  MessageDef::oneof_iterator iter(md);
+  upb_msg_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline OneofDef* MessageDef::oneof_iterator::operator*() const {
+  return upb_msg_iter_oneof(&iter_);
+}
+inline void MessageDef::oneof_iterator::operator++() {
+  return upb_msg_oneof_next(&iter_);
+}
+inline bool MessageDef::oneof_iterator::operator==(
+    const oneof_iterator &other) const {
+  return upb_strtable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::oneof_iterator::operator!=(
+    const oneof_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::const_oneof_iterator::const_oneof_iterator(
+    const MessageDef* md) {
+  upb_msg_oneof_begin(&iter_, md);
+}
+inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end(
+    const MessageDef *md) {
+  MessageDef::const_oneof_iterator iter(md);
+  upb_msg_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const {
+  return upb_msg_iter_oneof(&iter_);
+}
+inline void MessageDef::const_oneof_iterator::operator++() {
+  return upb_msg_oneof_next(&iter_);
+}
+inline bool MessageDef::const_oneof_iterator::operator==(
+    const const_oneof_iterator &other) const {
+  return upb_strtable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::const_oneof_iterator::operator!=(
+    const const_oneof_iterator &other) const {
   return !(*this == other);
 }
 
@@ -2495,6 +2930,105 @@
 }
 inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); }
 inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); }
+
+inline reffed_ptr<OneofDef> OneofDef::New() {
+  upb_oneofdef *o = upb_oneofdef_new(&o);
+  return reffed_ptr<OneofDef>(o, &o);
+}
+inline bool OneofDef::IsFrozen() const { return upb_oneofdef_isfrozen(this); }
+inline void OneofDef::Ref(const void* owner) const {
+  return upb_oneofdef_ref(this, owner);
+}
+inline void OneofDef::Unref(const void* owner) const {
+  return upb_oneofdef_unref(this, owner);
+}
+inline void OneofDef::DonateRef(const void* from, const void* to) const {
+  return upb_oneofdef_donateref(this, from, to);
+}
+inline void OneofDef::CheckRef(const void* owner) const {
+  return upb_oneofdef_checkref(this, owner);
+}
+inline const char* OneofDef::full_name() const {
+  return upb_oneofdef_name(this);
+}
+
+inline const MessageDef* OneofDef::containing_type() const {
+  return upb_oneofdef_containingtype(this);
+}
+inline const char* OneofDef::name() const {
+  return upb_oneofdef_name(this);
+}
+inline bool OneofDef::set_name(const char* name, Status* s) {
+  return upb_oneofdef_setname(this, name, s);
+}
+inline int OneofDef::field_count() const {
+  return upb_oneofdef_numfields(this);
+}
+inline bool OneofDef::AddField(FieldDef* field, Status* s) {
+  return upb_oneofdef_addfield(this, field, NULL, s);
+}
+inline bool OneofDef::AddField(const reffed_ptr<FieldDef>& field, Status* s) {
+  return upb_oneofdef_addfield(this, field.get(), NULL, s);
+}
+inline const FieldDef* OneofDef::FindFieldByName(const char* name,
+                                                 size_t len) const {
+  return upb_oneofdef_ntof(this, name, len);
+}
+inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const {
+  return upb_oneofdef_itof(this, num);
+}
+inline OneofDef::iterator OneofDef::begin() { return iterator(this); }
+inline OneofDef::iterator OneofDef::end() { return iterator::end(this); }
+inline OneofDef::const_iterator OneofDef::begin() const {
+  return const_iterator(this);
+}
+inline OneofDef::const_iterator OneofDef::end() const {
+  return const_iterator::end(this);
+}
+
+inline OneofDef::iterator::iterator(OneofDef* o) {
+  upb_oneof_begin(&iter_, o);
+}
+inline OneofDef::iterator OneofDef::iterator::end(OneofDef* o) {
+  OneofDef::iterator iter(o);
+  upb_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline FieldDef* OneofDef::iterator::operator*() const {
+  return upb_oneof_iter_field(&iter_);
+}
+inline void OneofDef::iterator::operator++() { return upb_oneof_next(&iter_); }
+inline bool OneofDef::iterator::operator==(const iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool OneofDef::iterator::operator!=(const iterator &other) const {
+  return !(*this == other);
+}
+
+inline OneofDef::const_iterator::const_iterator(const OneofDef* md) {
+  upb_oneof_begin(&iter_, md);
+}
+inline OneofDef::const_iterator OneofDef::const_iterator::end(
+    const OneofDef *md) {
+  OneofDef::const_iterator iter(md);
+  upb_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const FieldDef* OneofDef::const_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void OneofDef::const_iterator::operator++() {
+  return upb_oneof_next(&iter_);
+}
+inline bool OneofDef::const_iterator::operator==(
+    const const_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool OneofDef::const_iterator::operator!=(
+    const const_iterator &other) const {
+  return !(*this == other);
+}
+
 }  // namespace upb
 #endif
 
@@ -7295,12 +7829,30 @@
 
 UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser);
 
-// Internal-only struct used by the parser.
+// Internal-only struct used by the parser. A parser frame corresponds
+// one-to-one with a handler (sink) frame.
 typedef struct {
  UPB_PRIVATE_FOR_CPP
   upb_sink sink;
+  // The current message in which we're parsing, and the field whose value we're
+  // expecting next.
   const upb_msgdef *m;
   const upb_fielddef *f;
+
+  // We are in a repeated-field context, ready to emit mapentries as
+  // submessages. This flag alters the start-of-object (open-brace) behavior to
+  // begin a sequence of mapentry messages rather than a single submessage.
+  bool is_map;
+  // We are in a map-entry message context. This flag is set when parsing the
+  // value field of a single map entry and indicates to all value-field parsers
+  // (subobjects, strings, numbers, and bools) that the map-entry submessage
+  // should end as soon as the value is parsed.
+  bool is_mapentry;
+  // If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
+  // message's map field that we're currently parsing. This differs from |f|
+  // because |f| is the field in the *current* message (i.e., the map-entry
+  // message itself), not the parent's field that leads to this map.
+  const upb_fielddef *mapfield;
 } upb_jsonparser_frame;
 
 
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index 87033ac..371009b 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -7,7 +7,7 @@
 
 Gem::Specification.new do |s|
   s.name        = "google-protobuf"
-  s.version     = "3.0.0.alpha.2"
+  s.version     = "3.0.0.alpha.3.0.pre"
   s.licenses    = ["BSD"]
   s.summary     = "Protocol Buffers"
   s.description = "Protocol Buffers are Google's data interchange format."
@@ -18,5 +18,7 @@
   s.files       = ["lib/google/protobuf.rb"] +
                   # extension C source
                   find_c_source("ext/google/protobuf_c")
-  s.test_files = `git ls-files -- tests`.split
+  s.test_files = ["tests/basic.rb",
+		  "tests/stress.rb",
+		  "tests/generated_code_test.rb"]
 end
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 9265503..a78cc39 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -73,6 +73,15 @@
       optional :key, :string, 1
       optional :value, :message, 2, "TestMessage2"
     end
+
+    add_message "OneofMessage" do
+      oneof :my_oneof do
+        optional :a, :string, 1
+        optional :b, :int32, 2
+        optional :c, :message, 3, "TestMessage2"
+        optional :d, :enum, 4, "TestEnum"
+      end
+    end
   end
 
   TestMessage = pool.lookup("TestMessage").msgclass
@@ -87,6 +96,7 @@
     pool.lookup("MapMessageWireEquiv_entry1").msgclass
   MapMessageWireEquiv_entry2 =
     pool.lookup("MapMessageWireEquiv_entry2").msgclass
+  OneofMessage = pool.lookup("OneofMessage").msgclass
 
 # ------------ test cases ---------------
 
@@ -226,7 +236,8 @@
       assert l.count == 0
       l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
       assert l.count == 3
-      assert l == [1, 2, 3]
+      assert_equal [1, 2, 3], l
+      assert_equal l, [1, 2, 3]
       l.push 4
       assert l == [1, 2, 3, 4]
       dst_list = []
@@ -380,7 +391,7 @@
       # We only assert on inspect value when there is one map entry because the
       # order in which elements appear is unspecified (depends on the internal
       # hash function). We don't want a brittle test.
-      assert m.inspect == "{\"jkl;\" => 42}"
+      assert m.inspect == "{\"jkl;\"=>42}"
 
       assert m.keys == ["jkl;"]
       assert m.values == [42]
@@ -582,6 +593,91 @@
                     "b" => TestMessage2.new(:foo => 2)}
     end
 
+    def test_oneof_descriptors
+      d = OneofMessage.descriptor
+      o = d.lookup_oneof("my_oneof")
+      assert o != nil
+      assert o.class == Google::Protobuf::OneofDescriptor
+      assert o.name == "my_oneof"
+      oneof_count = 0
+      d.each_oneof{ |oneof|
+        oneof_count += 1
+        assert oneof == o
+      }
+      assert oneof_count == 1
+      assert o.count == 4
+      field_names = o.map{|f| f.name}.sort
+      assert field_names == ["a", "b", "c", "d"]
+    end
+
+    def test_oneof
+      d = OneofMessage.new
+      assert d.a == nil
+      assert d.b == nil
+      assert d.c == nil
+      assert d.d == nil
+      assert d.my_oneof == nil
+
+      d.a = "hi"
+      assert d.a == "hi"
+      assert d.b == nil
+      assert d.c == nil
+      assert d.d == nil
+      assert d.my_oneof == :a
+
+      d.b = 42
+      assert d.a == nil
+      assert d.b == 42
+      assert d.c == nil
+      assert d.d == nil
+      assert d.my_oneof == :b
+
+      d.c = TestMessage2.new(:foo => 100)
+      assert d.a == nil
+      assert d.b == nil
+      assert d.c.foo == 100
+      assert d.d == nil
+      assert d.my_oneof == :c
+
+      d.d = :C
+      assert d.a == nil
+      assert d.b == nil
+      assert d.c == nil
+      assert d.d == :C
+      assert d.my_oneof == :d
+
+      d2 = OneofMessage.decode(OneofMessage.encode(d))
+      assert d2 == d
+
+      encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
+      encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
+      encoded_field_c = OneofMessage.encode(
+        OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
+      encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
+
+      d3 = OneofMessage.decode(
+        encoded_field_c + encoded_field_a + encoded_field_d)
+      assert d3.a == nil
+      assert d3.b == nil
+      assert d3.c == nil
+      assert d3.d == :B
+
+      d4 = OneofMessage.decode(
+        encoded_field_c + encoded_field_a + encoded_field_d +
+        encoded_field_c)
+      assert d4.a == nil
+      assert d4.b == nil
+      assert d4.c.foo == 1
+      assert d4.d == nil
+
+      d5 = OneofMessage.new(:a => "hello")
+      assert d5.a != nil
+      d5.a = nil
+      assert d5.a == nil
+      assert OneofMessage.encode(d5) == ''
+      assert d5.my_oneof == nil
+    end
+
     def test_enum_field
       m = TestMessage.new
       assert m.optional_enum == :Default
@@ -621,6 +717,14 @@
       assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
     end
 
+    def test_eq
+      m = TestMessage.new(:optional_int32 => 42,
+                          :repeated_int32 => [1, 2, 3])
+      m2 = TestMessage.new(:optional_int32 => 43,
+                           :repeated_int32 => [1, 2, 3])
+      assert m != m2
+    end
+
     def test_enum_lookup
       assert TestEnum::A == 1
       assert TestEnum::B == 2
@@ -888,5 +992,13 @@
       m2 = TestMessage.decode_json(json_text)
       assert m == m2
     end
+
+    def test_json_maps
+      m = MapMessage.new(:map_string_int32 => {"a" => 1})
+      expected = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
+      assert MapMessage.encode_json(m) == expected
+      m2 = MapMessage.decode_json(MapMessage.encode_json(m))
+      assert m == m2
+    end
   end
 end
diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto
new file mode 100644
index 0000000..b1d6323
--- /dev/null
+++ b/ruby/tests/generated_code.proto
@@ -0,0 +1,67 @@
+syntax = "proto3";
+
+package A.B.C;
+
+message TestMessage {
+  optional int32 optional_int32 = 1;
+  optional int64 optional_int64 = 2;
+  optional uint32 optional_uint32 = 3;
+  optional uint64 optional_uint64 = 4;
+  optional bool optional_bool = 5;
+  optional double optional_double = 6;
+  optional float optional_float = 7;
+  optional string optional_string = 8;
+  optional bytes optional_bytes = 9;
+  optional TestEnum optional_enum = 10;
+  optional TestMessage optional_msg = 11;
+
+  repeated int32 repeated_int32 = 21;
+  repeated int64 repeated_int64 = 22;
+  repeated uint32 repeated_uint32 = 23;
+  repeated uint64 repeated_uint64 = 24;
+  repeated bool repeated_bool = 25;
+  repeated double repeated_double = 26;
+  repeated float repeated_float = 27;
+  repeated string repeated_string = 28;
+  repeated bytes repeated_bytes = 29;
+  repeated TestEnum repeated_enum = 30;
+  repeated TestMessage repeated_msg = 31;
+
+  oneof my_oneof {
+    int32 oneof_int32 = 41;
+    int64 oneof_int64 = 42;
+    uint32 oneof_uint32 = 43;
+    uint64 oneof_uint64 = 44;
+    bool oneof_bool = 45;
+    double oneof_double = 46;
+    float oneof_float = 47;
+    string oneof_string = 48;
+    bytes oneof_bytes = 49;
+    TestEnum oneof_enum = 50;
+    TestMessage oneof_msg = 51;
+  }
+
+  map<int32, string> map_int32_string = 61;
+  map<int64, string> map_int64_string = 62;
+  map<uint32, string> map_uint32_string = 63;
+  map<uint64, string> map_uint64_string = 64;
+  map<bool, string> map_bool_string = 65;
+  map<string, string> map_string_string = 66;
+  map<string, TestMessage> map_string_msg = 67;
+  map<string, TestEnum> map_string_enum = 68;
+  map<string, int32> map_string_int32 = 69;
+  map<string, bool> map_string_bool = 70;
+
+  message NestedMessage {
+    optional int32 foo = 1;
+  }
+
+  optional NestedMessage nested_message = 80;
+}
+
+enum TestEnum {
+  Default = 0;
+  A = 1;
+  B = 2;
+  C = 3;
+}
diff --git a/ruby/tests/generated_code.rb b/ruby/tests/generated_code.rb
new file mode 100644
index 0000000..5a68543
--- /dev/null
+++ b/ruby/tests/generated_code.rb
@@ -0,0 +1,74 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: generated_code.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "A.B.C.TestMessage" do
+    optional :optional_int32, :int32, 1
+    optional :optional_int64, :int64, 2
+    optional :optional_uint32, :uint32, 3
+    optional :optional_uint64, :uint64, 4
+    optional :optional_bool, :bool, 5
+    optional :optional_double, :double, 6
+    optional :optional_float, :float, 7
+    optional :optional_string, :string, 8
+    optional :optional_bytes, :string, 9
+    optional :optional_enum, :enum, 10, "A.B.C.TestEnum"
+    optional :optional_msg, :message, 11, "A.B.C.TestMessage"
+    repeated :repeated_int32, :int32, 21
+    repeated :repeated_int64, :int64, 22
+    repeated :repeated_uint32, :uint32, 23
+    repeated :repeated_uint64, :uint64, 24
+    repeated :repeated_bool, :bool, 25
+    repeated :repeated_double, :double, 26
+    repeated :repeated_float, :float, 27
+    repeated :repeated_string, :string, 28
+    repeated :repeated_bytes, :string, 29
+    repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
+    repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
+    map :map_int32_string, :int32, :string, 61
+    map :map_int64_string, :int64, :string, 62
+    map :map_uint32_string, :uint32, :string, 63
+    map :map_uint64_string, :uint64, :string, 64
+    map :map_bool_string, :bool, :string, 65
+    map :map_string_string, :string, :string, 66
+    map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage"
+    map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum"
+    map :map_string_int32, :string, :int32, 69
+    map :map_string_bool, :string, :bool, 70
+    optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage"
+    oneof :my_oneof do
+      optional :oneof_int32, :int32, 41
+      optional :oneof_int64, :int64, 42
+      optional :oneof_uint32, :uint32, 43
+      optional :oneof_uint64, :uint64, 44
+      optional :oneof_bool, :bool, 45
+      optional :oneof_double, :double, 46
+      optional :oneof_float, :float, 47
+      optional :oneof_string, :string, 48
+      optional :oneof_bytes, :string, 49
+      optional :oneof_enum, :enum, 50, "A.B.C.TestEnum"
+      optional :oneof_msg, :message, 51, "A.B.C.TestMessage"
+    end
+  end
+  add_message "A.B.C.TestMessage.NestedMessage" do
+    optional :foo, :int32, 1
+  end
+  add_enum "A.B.C.TestEnum" do
+    value :Default, 0
+    value :A, 1
+    value :B, 2
+    value :C, 3
+  end
+end
+
+module A
+  module B
+    module C
+      TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass
+      TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass
+      TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule
+    end
+  end
+end
diff --git a/ruby/tests/generated_code_test.rb b/ruby/tests/generated_code_test.rb
new file mode 100644
index 0000000..daef357
--- /dev/null
+++ b/ruby/tests/generated_code_test.rb
@@ -0,0 +1,17 @@
+#!/usr/bin/ruby
+
+# generated_code.rb is in the same directory as this test.
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
+
+require 'generated_code'
+require 'test/unit'
+
+class GeneratedCodeTest < Test::Unit::TestCase
+  def test_generated_msg
+    # just test that we can instantiate the message. The purpose of this test
+    # is to ensure that the output of the code generator is valid Ruby and
+    # successfully creates message definitions and classes, not to test every
+    # aspect of the extension (basic.rb is for that).
+    m = A::B::C::TestMessage.new()
+  end
+end
diff --git a/src/Makefile.am b/src/Makefile.am
index 3a469fd..63a1451 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,17 +31,30 @@
 clean-local:
 	rm -f *.loT
 
-CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
+public_config = google/protobuf/stubs/pbconfig.h
+
+CLEANFILES = $(protoc_outputs) $(public_config) unittest_proto_middleman \
              testzip.jar testzip.list testzip.proto testzip.zip
 
 MAINTAINERCLEANFILES =   \
   Makefile.in
 
+# Generate and distribute a minimum config.h file to make hash_map work.
+# The autoheader config has too much info, which might conflict with other
+# macros applications might include. Thus, we create a stubs/pbconfig.h, that
+# only #defines what we really need, and prefix it with GOOGLE_PROTOBUF_ to
+# avoid conflicts.
+$(public_config): $(top_builddir)/config.h $(top_srcdir)/config.h.include
+	echo "// Note: Google Protobuf internal only. Do NOT include." > $@
+	cat $(top_builddir)/config.h | grep -f $(top_srcdir)/config.h.include | \
+	sed 's,#define , #define GOOGLE_PROTOBUF_,' >> $@
+
 nobase_include_HEADERS =                                        \
   google/protobuf/stubs/atomic_sequence_num.h                   \
   google/protobuf/stubs/atomicops.h                             \
   google/protobuf/stubs/atomicops_internals_aix.h               \
   google/protobuf/stubs/atomicops_internals_arm64_gcc.h         \
+  google/protobuf/stubs/atomicops_internals_tile_gcc.h          \
   google/protobuf/stubs/atomicops_internals_arm_gcc.h           \
   google/protobuf/stubs/atomicops_internals_arm_qnx.h           \
   google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
@@ -54,11 +67,13 @@
   google/protobuf/stubs/atomicops_internals_x86_gcc.h           \
   google/protobuf/stubs/atomicops_internals_x86_msvc.h          \
   google/protobuf/stubs/casts.h                                 \
-  google/protobuf/stubs/singleton.h                             \
   google/protobuf/stubs/common.h                                \
   google/protobuf/stubs/fastmem.h                               \
+  google/protobuf/stubs/hash.h                                  \
   google/protobuf/stubs/once.h                                  \
   google/protobuf/stubs/platform_macros.h                       \
+  google/protobuf/stubs/shared_ptr.h                            \
+  google/protobuf/stubs/singleton.h                             \
   google/protobuf/stubs/stl_util.h                              \
   google/protobuf/stubs/template_util.h                         \
   google/protobuf/stubs/type_traits.h                           \
@@ -70,10 +85,13 @@
   google/protobuf/dynamic_message.h                             \
   google/protobuf/extension_set.h                               \
   google/protobuf/generated_enum_reflection.h                   \
+  google/protobuf/generated_enum_util.h                         \
   google/protobuf/generated_message_reflection.h                \
   google/protobuf/generated_message_util.h                      \
   google/protobuf/map_entry.h                                   \
+  google/protobuf/map_entry_lite.h                              \
   google/protobuf/map_field.h                                   \
+  google/protobuf/map_field_lite.h                              \
   google/protobuf/map_field_inl.h                               \
   google/protobuf/map.h                                         \
   google/protobuf/map_type_handler.h                            \
@@ -111,6 +129,9 @@
   google/protobuf/compiler/python/python_generator.h            \
   google/protobuf/compiler/ruby/ruby_generator.h
 
+nobase_nodist_include_HEADERS =                                 \
+  $(public_config)
+
 lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
 
 libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
@@ -136,6 +157,7 @@
   google/protobuf/io/coded_stream_inl.h                        \
   google/protobuf/io/zero_copy_stream.cc                       \
   google/protobuf/io/zero_copy_stream_impl_lite.cc
+nodist_libprotobuf_lite_la_SOURCES = $(public_config)
 
 libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
 libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
@@ -167,6 +189,7 @@
   google/protobuf/io/zero_copy_stream_impl.cc                  \
   google/protobuf/compiler/importer.cc                         \
   google/protobuf/compiler/parser.cc
+nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
 
 libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
 libprotoc_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
@@ -243,26 +266,28 @@
   google/protobuf/compiler/java/java_doc_comment.cc            \
   google/protobuf/compiler/java/java_doc_comment.h             \
   google/protobuf/compiler/javanano/javanano_enum.cc           \
+  google/protobuf/compiler/javanano/javanano_enum.h            \
+  google/protobuf/compiler/javanano/javanano_enum_field.cc     \
   google/protobuf/compiler/javanano/javanano_enum_field.h      \
   google/protobuf/compiler/javanano/javanano_extension.cc      \
+  google/protobuf/compiler/javanano/javanano_extension.h       \
   google/protobuf/compiler/javanano/javanano_field.cc          \
+  google/protobuf/compiler/javanano/javanano_field.h           \
   google/protobuf/compiler/javanano/javanano_file.cc           \
+  google/protobuf/compiler/javanano/javanano_file.h            \
   google/protobuf/compiler/javanano/javanano_generator.cc      \
+  google/protobuf/compiler/javanano/javanano_generator.h       \
   google/protobuf/compiler/javanano/javanano_helpers.cc        \
+  google/protobuf/compiler/javanano/javanano_helpers.h         \
+  google/protobuf/compiler/javanano/javanano_map_field.cc      \
+  google/protobuf/compiler/javanano/javanano_map_field.h       \
   google/protobuf/compiler/javanano/javanano_message.cc        \
+  google/protobuf/compiler/javanano/javanano_message.h         \
+  google/protobuf/compiler/javanano/javanano_message_field.cc  \
   google/protobuf/compiler/javanano/javanano_message_field.h   \
   google/protobuf/compiler/javanano/javanano_params.h          \
-  google/protobuf/compiler/javanano/javanano_primitive_field.h \
-  google/protobuf/compiler/javanano/javanano_enum_field.cc     \
-  google/protobuf/compiler/javanano/javanano_enum.h            \
-  google/protobuf/compiler/javanano/javanano_extension.h       \
-  google/protobuf/compiler/javanano/javanano_field.h           \
-  google/protobuf/compiler/javanano/javanano_file.h            \
-  google/protobuf/compiler/javanano/javanano_generator.h       \
-  google/protobuf/compiler/javanano/javanano_helpers.h         \
-  google/protobuf/compiler/javanano/javanano_message_field.cc  \
-  google/protobuf/compiler/javanano/javanano_message.h         \
   google/protobuf/compiler/javanano/javanano_primitive_field.cc \
+  google/protobuf/compiler/javanano/javanano_primitive_field.h \
   google/protobuf/compiler/python/python_generator.cc          \
   google/protobuf/compiler/ruby/ruby_generator.cc
 
@@ -295,6 +320,7 @@
   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/compiler/cpp/cpp_test_bad_identifiers.proto
 
@@ -305,6 +331,7 @@
   google/protobuf/io/gzip_stream_unittest.sh                   \
   google/protobuf/testdata/golden_message                      \
   google/protobuf/testdata/golden_message_oneof_implemented    \
+  google/protobuf/testdata/golden_message_proto3               \
   google/protobuf/testdata/golden_packed_fields_message        \
   google/protobuf/testdata/bad_utf8_string                     \
   google/protobuf/testdata/text_format_unittest_data.txt       \
@@ -320,6 +347,8 @@
   google/protobuf/unittest_enormous_descriptor.proto
 
 protoc_lite_outputs =                                          \
+  google/protobuf/map_lite_unittest.pb.cc                      \
+  google/protobuf/map_lite_unittest.pb.h                       \
   google/protobuf/unittest_lite.pb.cc                          \
   google/protobuf/unittest_lite.pb.h                           \
   google/protobuf/unittest_import_lite.pb.cc                   \
@@ -329,8 +358,6 @@
 
 protoc_outputs =                                               \
   $(protoc_lite_outputs)                                       \
-  google/protobuf/map_lite_unittest.pb.cc                      \
-  google/protobuf/map_lite_unittest.pb.h                       \
   google/protobuf/map_proto2_unittest.pb.cc                    \
   google/protobuf/map_proto2_unittest.pb.h                     \
   google/protobuf/map_unittest.pb.cc                           \
@@ -367,12 +394,14 @@
   google/protobuf/unittest_optimize_for.pb.h                   \
   google/protobuf/unittest_preserve_unknown_enum.pb.cc         \
   google/protobuf/unittest_preserve_unknown_enum.pb.h          \
+  google/protobuf/unittest_preserve_unknown_enum2.pb.cc        \
+  google/protobuf/unittest_preserve_unknown_enum2.pb.h         \
   google/protobuf/unittest_proto3_arena.pb.cc                  \
   google/protobuf/unittest_proto3_arena.pb.h                   \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc  \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
 
-BUILT_SOURCES = $(protoc_outputs)
+BUILT_SOURCES = $(public_config) $(protoc_outputs)
 
 if USE_EXTERNAL_PROTOC
 
@@ -394,8 +423,11 @@
 $(protoc_outputs): unittest_proto_middleman
 
 COMMON_TEST_SOURCES =                                          \
+  google/protobuf/arena_test_util.cc                           \
+  google/protobuf/arena_test_util.h                            \
   google/protobuf/map_test_util.cc                             \
   google/protobuf/map_test_util.h                              \
+  google/protobuf/map_test_util_impl.h                         \
   google/protobuf/test_util.cc                                 \
   google/protobuf/test_util.h                                  \
   google/protobuf/testing/googletest.cc                        \
@@ -458,6 +490,7 @@
   google/protobuf/compiler/java/java_plugin_unittest.cc        \
   google/protobuf/compiler/java/java_doc_comment_unittest.cc   \
   google/protobuf/compiler/python/python_plugin_unittest.cc    \
+  google/protobuf/compiler/ruby/ruby_generator_unittest.cc     \
   $(COMMON_TEST_SOURCES)
 nodist_protobuf_test_SOURCES = $(protoc_outputs)
 
@@ -480,8 +513,12 @@
 protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
 protobuf_lite_test_SOURCES =                                           \
   google/protobuf/lite_unittest.cc                                     \
+  google/protobuf/map_lite_test_util.cc                                \
+  google/protobuf/map_lite_test_util.h                                 \
   google/protobuf/test_util_lite.cc                                    \
   google/protobuf/test_util_lite.h
+  # TODO(teboring) add the file back and make the test build.
+  # google/protobuf/map_lite_test.cc
 nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
 
 # Test plugin binary.
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
new file mode 100644
index 0000000..bf2aa0a
--- /dev/null
+++ b/src/google/protobuf/any.proto
@@ -0,0 +1,98 @@
+// 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 google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "AnyProto";
+option java_package = "com.google.protobuf";
+
+
+// `Any` contains an arbitrary serialized message along with a URL
+// that describes the type of the serialized message.
+//
+//
+//
+// # JSON
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+//     package google.profile;
+//     message Person {
+//       string first_name = 1;
+//       string last_name = 2;
+//     }
+//
+//     {
+//       "@type": "type.googleapis.com/google.profile.Person",
+//       "firstName": <string>,
+//       "lastName": <string>
+//     }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the the `@type`
+// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]):
+//
+//     {
+//       "@type": "type.googleapis.com/google.protobuf.Duration",
+//       "value": "1.212s"
+//     }
+//
+message Any {
+  // A URL/resource name whose content describes the type of the
+  // serialized message.
+  //
+  // For URLs which use the schema `http`, `https`, or no schema, the
+  // following restrictions and interpretations apply:
+  //
+  // * If no schema is provided, https is assumed.
+  // * The last segment of the URL's path must represent the fully
+  //   qualified name of the type (as in `path/google.protobuf.Duration`).
+  // * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type]
+  //   value in binary format, or produce an error.
+  // * Applications are allowed to cache lookup results based on the
+  //   URL, or have them precompiled into a binary to avoid any
+  //   lookup. Therefore, binary compatibility need to be preserved
+  //   on changes to types. (Use versioned type names to manage
+  //   breaking changes.)
+  //
+  // Schemas other than `http`, `https` (or the empty schema) might be
+  // used with implementation specific semantics.
+  //
+  //
+  string type_url = 1;
+
+  // Must be valid serialized data of the above specified type.
+  bytes value = 2;
+}
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
old mode 100644
new mode 100755
index 1853678..bda3741
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -47,35 +47,53 @@
 GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
 #endif
 
-void Arena::Init(const ArenaOptions& options) {
+void Arena::Init() {
   lifecycle_id_ = lifecycle_id_generator_.GetNext();
-  start_block_size_ = options.start_block_size;
-  max_block_size_ = options.max_block_size;
-  block_alloc = options.block_alloc;
-  block_dealloc = options.block_dealloc;
   blocks_ = 0;
   hint_ = 0;
   owns_first_block_ = true;
   cleanup_list_ = 0;
 
-  if (options.initial_block != NULL && options.initial_block_size > 0) {
+  if (options_.initial_block != NULL && options_.initial_block_size > 0) {
     // Add first unowned block to list.
-    Block* first_block = reinterpret_cast<Block*>(options.initial_block);
-    first_block->size = options.initial_block_size;
+    Block* first_block = reinterpret_cast<Block*>(options_.initial_block);
+    first_block->size = options_.initial_block_size;
     first_block->pos = kHeaderSize;
     first_block->next = NULL;
     first_block->owner = &first_block->owner;
     AddBlock(first_block);
     owns_first_block_ = false;
   }
+
+  // Call the initialization hook
+  if (options_.on_arena_init != NULL) {
+    hooks_cookie_ = options_.on_arena_init(this);
+  } else {
+    hooks_cookie_ = NULL;
+  }
+}
+
+Arena::~Arena() {
+  uint64 space_allocated = Reset();
+
+  // Call the destruction hook
+  if (options_.on_arena_destruction != NULL) {
+    options_.on_arena_destruction(this, hooks_cookie_, space_allocated);
+  }
 }
 
 uint64 Arena::Reset() {
   CleanupList();
-  uint64 space_used = FreeBlocks();
+  uint64 space_allocated = FreeBlocks();
   // Invalidate any ThreadCaches pointing to any blocks we just destroyed.
   lifecycle_id_ = lifecycle_id_generator_.GetNext();
-  return space_used;
+
+  // Call the reset hook
+  if (options_.on_arena_reset != NULL) {
+    options_.on_arena_reset(this, hooks_cookie_, space_allocated);
+  }
+
+  return space_allocated;
 }
 
 Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
@@ -93,7 +111,7 @@
     size = kHeaderSize + n;
   }
 
-  Block* b = reinterpret_cast<Block*>(block_alloc(size));
+  Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
   b->pos = kHeaderSize + n;
   b->size = size;
   if (b->avail() == 0) {
@@ -184,7 +202,7 @@
     google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
     return AllocFromBlock(b, n);
   }
-  b = NewBlock(me, b, n, start_block_size_, max_block_size_);
+  b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
   AddBlock(b);
   if (b->owner == me) {  // If this block can be reused (see NewBlock()).
     SetThreadCacheBlock(b);
@@ -192,29 +210,38 @@
   return reinterpret_cast<char*>(b) + kHeaderSize;
 }
 
+uint64 Arena::SpaceAllocated() const {
+  uint64 space_allocated = 0;
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  while (b != NULL) {
+    space_allocated += (b->size);
+    b = b->next;
+  }
+  return space_allocated;
+}
+
 uint64 Arena::SpaceUsed() const {
   uint64 space_used = 0;
   Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
   while (b != NULL) {
-    space_used += (b->size);
+    space_used += (b->pos - kHeaderSize);
     b = b->next;
   }
   return space_used;
 }
 
-
 uint64 Arena::FreeBlocks() {
-  uint64 space_used = 0;
+  uint64 space_allocated = 0;
   Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
   Block* first_block = NULL;
   while (b != NULL) {
-    space_used += (b->size);
+    space_allocated += (b->size);
     Block* next = b->next;
     if (next != NULL) {
-      block_dealloc(b, b->size);
+      options_.block_dealloc(b, b->size);
     } else {
       if (owns_first_block_) {
-        block_dealloc(b, b->size);
+        options_.block_dealloc(b, b->size);
       } else {
         // User passed in the first block, skip free'ing the memory.
         first_block = b;
@@ -231,7 +258,7 @@
     first_block->owner = &first_block->owner;
     AddBlock(first_block);
   }
-  return space_used;
+  return space_allocated;
 }
 
 void Arena::CleanupList() {
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index d0cb163..bb15e80 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -34,9 +34,11 @@
 #ifndef GOOGLE_PROTOBUF_ARENA_H__
 #define GOOGLE_PROTOBUF_ARENA_H__
 
-#include <google/protobuf/stubs/common.h>
+#include <typeinfo>
+
 #include <google/protobuf/stubs/atomic_sequence_num.h>
 #include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/type_traits.h>
 
 namespace google {
@@ -89,19 +91,44 @@
 
   // A function pointer to an alloc method that returns memory blocks of size
   // requested. By default, it contains a ptr to the malloc function.
+  //
+  // NOTE: block_alloc and dealloc functions are expected to behave like
+  // malloc and free, including Asan poisoning.
   void* (*block_alloc)(size_t);
   // A function pointer to a dealloc method that takes ownership of the blocks
   // from the arena. By default, it contains a ptr to a wrapper function that
   // calls free.
   void (*block_dealloc)(void*, size_t);
 
+  // Hooks for adding external functionality such as user-specific metrics
+  // collection, specific debugging abilities, etc.
+  // Init hook may return a pointer to a cookie to be stored in the arena.
+  // reset and destruction hooks will then be called with the same cookie
+  // pointer. This allows us to save an external object per arena instance and
+  // use it on the other hooks (Note: It is just as legal for init to return
+  // NULL and not use the cookie feature).
+  // on_arena_reset and on_arena_destruction also receive the space used in
+  // the arena just before the reset.
+  void* (*on_arena_init)(Arena* arena);
+  void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
+  void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
+
+  // type_name is promised to be a static string - its lifetime extends to
+  // match program's lifetime.
+  void (*on_arena_allocation)(const char* type_name, uint64 alloc_size,
+      Arena* arena, void* cookie);
+
   ArenaOptions()
       : start_block_size(kDefaultStartBlockSize),
         max_block_size(kDefaultMaxBlockSize),
         initial_block(NULL),
         initial_block_size(0),
         block_alloc(&malloc),
-        block_dealloc(&internal::arena_free) {}
+        block_dealloc(&internal::arena_free),
+        on_arena_init(NULL),
+        on_arena_reset(NULL),
+        on_arena_destruction(NULL),
+        on_arena_allocation(NULL) {}
 
  private:
   // Constants define default starting block size and max block size for
@@ -123,23 +150,21 @@
  public:
   // Arena constructor taking custom options. See ArenaOptions below for
   // descriptions of the options available.
-  explicit Arena(const ArenaOptions& options) {
-    Init(options);
+  explicit Arena(const ArenaOptions& options) : options_(options) {
+    Init();
   }
 
   // Default constructor with sensible default options, tuned for average
   // use-cases.
   Arena() {
-    Init(ArenaOptions());
+    Init();
   }
 
   // Destructor deletes all owned heap allocated objects, and destructs objects
   // that have non-trivial destructors, except for proto2 message objects whose
   // destructors can be skipped. Also, frees all blocks except the initial block
   // if it was passed in.
-  ~Arena() {
-    Reset();
-  }
+  ~Arena();
 
   // API to create proto2 message objects on the arena. If the arena passed in
   // is NULL, then a heap allocated object is returned. Type T must be a message
@@ -195,6 +220,40 @@
     }
   }
 
+  // Version of the above with three constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3);
+    } else {
+      return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+                                      arg1,
+                                      arg2,
+                                      arg3);
+    }
+  }
+
+  // Version of the above with four constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3, const Arg4& arg4) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3, arg4);
+    } else {
+      return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+                                      arg1,
+                                      arg2,
+                                      arg3,
+                                      arg4);
+    }
+  }
+
   // Create an array of object type T on the arena. Type T must have a trivial
   // constructor, as it will not be invoked when created on the arena.
   template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
@@ -202,8 +261,7 @@
     if (arena == NULL) {
       return new T[num_elements];
     } else {
-      return static_cast<T*>(
-          arena->AllocateAligned(num_elements * sizeof(T)));
+      return arena->CreateInternalRawArray<T>(num_elements);
     }
   }
 
@@ -211,6 +269,8 @@
   // of the underlying blocks. The total space used may not include the new
   // blocks that are allocated by this arena from other threads concurrently
   // with the call to this method.
+  uint64 SpaceAllocated() const GOOGLE_ATTRIBUTE_NOINLINE;
+  // As above, but does not include any free space in underlying blocks.
   uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE;
 
   // Frees all storage allocated by this arena after calling destructors
@@ -253,7 +313,7 @@
   // latter is a virtual call, while this method is a templated call that
   // resolves at compile-time.
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static inline ::google::protobuf::Arena* GetArena(T* value) {
+  static inline ::google::protobuf::Arena* GetArena(const T* value) {
     return GetArenaInternal(value, static_cast<T*>(0));
   }
 
@@ -295,9 +355,6 @@
     // data follows
   };
 
-  void* (*block_alloc)(size_t);  // Allocates a free block of a particular size.
-  void (*block_dealloc)(void*, size_t);  // Deallocates the given block.
-
   template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
   friend class MockArena;              // For unit-testing.
   friend class internal::ArenaString;  // For AllocateAligned.
@@ -313,6 +370,8 @@
   static const size_t kHeaderSize = sizeof(Block);
   static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
 #ifdef PROTOBUF_USE_DLLS
+  // Thread local variables cannot be exposed through DLL interface but we can
+  // wrap them in static functions.
   static ThreadCache& thread_cache();
 #else
   static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
@@ -352,6 +411,13 @@
     return Create<T>(arena);
   }
 
+  // Just allocate the required size for the given type assuming the
+  // type has a trivial constructor.
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  inline T* CreateInternalRawArray(uint32 num_elements) {
+    return static_cast<T*>(AllocateAligned(sizeof(T) * num_elements));
+  }
+
   template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   inline T* CreateInternal(
       bool skip_explicit_ownership) {
@@ -382,12 +448,57 @@
     return t;
   }
 
+  template <typename T, typename Arg1, typename Arg2, typename Arg3>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+                                                   const Arg1& arg1,
+                                                   const Arg2& arg2,
+                                                   const Arg3& arg3) {
+    T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+                                                   const Arg1& arg1,
+                                                   const Arg2& arg2,
+                                                   const Arg3& arg3,
+                                                   const Arg4& arg4) {
+    T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3, arg4);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
   template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
     return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
                                      this);
   }
 
+  // CreateInArenaStorage is used to implement map field. Without it,
+  // google::protobuf::Map need to call generated message's protected arena constructor,
+  // which needs to declare google::protobuf::Map as friend of generated message.
+  template <typename T>
+  static void CreateInArenaStorage(T* ptr, Arena* arena) {
+    CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value);
+  }
+  template <typename T>
+  static void CreateInArenaStorageInternal(
+      T* ptr, Arena* arena, google::protobuf::internal::true_type) {
+    new (ptr) T(arena);
+  }
+
+  template <typename T>
+  static void CreateInArenaStorageInternal(
+      T* ptr, Arena* arena, google::protobuf::internal::false_type) {
+    new (ptr) T;
+  }
+
   // These implement Own(), which registers an object for deletion (destructor
   // call and operator delete()). The second parameter has type 'true_type' if T
   // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
@@ -410,20 +521,20 @@
   // InternalArenaConstructable_ tags can be associated with an arena, and such
   // objects must implement a GetArenaNoVirtual() method.
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static inline ::google::protobuf::Arena* GetArenaInternal(T* value,
+  static inline ::google::protobuf::Arena* GetArenaInternal(const T* value,
       typename T::InternalArenaConstructable_*) {
     return value->GetArenaNoVirtual();
   }
 
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static inline ::google::protobuf::Arena* GetArenaInternal(T* value, ...) {
+  static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
     return NULL;
   }
 
 
   void* AllocateAligned(size_t size);
 
-  void Init(const ArenaOptions& options);
+  void Init();
 
   // Free all blocks and return the total space used which is the sums of sizes
   // of the all the allocated blocks.
@@ -444,8 +555,6 @@
   }
 
   int64 lifecycle_id_;  // Unique for each arena. Changes on Reset().
-  size_t start_block_size_;  // Starting block size of the arena.
-  size_t max_block_size_;    // Max block size of the arena.
 
   google::protobuf::internal::AtomicWord blocks_;  // Head of linked list of all allocated blocks
   google::protobuf::internal::AtomicWord hint_;    // Fast thread-local block access
@@ -470,6 +579,15 @@
   Block* NewBlock(void* me, Block* my_last_block, size_t n,
                   size_t start_block_size, size_t max_block_size);
   static void* AllocFromBlock(Block* b, size_t n);
+  template <typename Key, typename T>
+  friend class Map;
+
+  // The arena may save a cookie it receives from the external on_init hook
+  // and then use it when calling the on_reset and on_destruction hooks.
+  void* hooks_cookie_;
+
+  ArenaOptions options_;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
 };
 
diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
new file mode 100644
index 0000000..21f55c6
--- /dev/null
+++ b/src/google/protobuf/arena_test_util.cc
@@ -0,0 +1,49 @@
+// 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 <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+
+
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+NoHeapChecker::~NoHeapChecker() {
+  capture_alloc.Unhook();
+  EXPECT_EQ(0, capture_alloc.alloc_count());
+  EXPECT_EQ(0, capture_alloc.free_count());
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
new file mode 100644
index 0000000..7db7a90
--- /dev/null
+++ b/src/google/protobuf/arena_test_util.h
@@ -0,0 +1,59 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+class NoHeapChecker {
+ public:
+  NoHeapChecker() {
+    capture_alloc.Hook();
+  }
+  ~NoHeapChecker();
+ private:
+  class NewDeleteCapture {
+   public:
+    // TOOD(xiaofeng): Implement this for opensource protobuf.
+    void Hook() {}
+    void Unhook() {}
+    int alloc_count() { return 0; }
+    int free_count() { return 0; }
+  } capture_alloc;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 9d3d3e3..d9b198e 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/arena.h>
 
+#include <stdint.h>
+
 #include <algorithm>
 #include <cstring>
 #include <memory>
@@ -40,6 +42,7 @@
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_arena.pb.h>
@@ -91,6 +94,37 @@
  private:
   Notifier* notifier_;
 };
+
+// A simple class that does not allow copying and so cannot be used as a
+// parameter type without "const &".
+class PleaseDontCopyMe {
+ public:
+  explicit PleaseDontCopyMe(int value) : value_(value) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe);
+};
+
+// A class that takes four different types as constructor arguments.
+class MustBeConstructedWithOneThroughFour {
+ public:
+  MustBeConstructedWithOneThroughFour(
+      int one, const char* two, const string& three,
+      const PleaseDontCopyMe* four)
+      : one_(one), two_(two), three_(three), four_(four) {}
+
+  int one_;
+  const char* const two_;
+  string three_;
+  const PleaseDontCopyMe* four_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
+};
+
 }  // namespace
 
 TEST(ArenaTest, ArenaConstructable) {
@@ -122,6 +156,20 @@
   EXPECT_EQ(2, notifier.GetCount());
 }
 
+TEST(ArenaTest, CreateWithManyConstructorArguments) {
+  Arena arena;
+  const string three("3");
+  const PleaseDontCopyMe four(4);
+  const MustBeConstructedWithOneThroughFour* new_object =
+      Arena::Create<MustBeConstructedWithOneThroughFour>(
+          &arena, 1, "2", three, &four);
+  EXPECT_TRUE(new_object != NULL);
+  ASSERT_EQ(1, new_object->one_);
+  ASSERT_STREQ("2", new_object->two_);
+  ASSERT_EQ("3", new_object->three_);
+  ASSERT_EQ(4, new_object->four_->value());
+}
+
 TEST(ArenaTest, InitialBlockTooSmall) {
   // Construct a small (64 byte) initial block of memory to be used by the
   // arena allocator; then, allocate an object which will not fit in the
@@ -380,6 +428,7 @@
   delete nested_string;
 }
 
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
 TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
   TestAllTypes::NestedMessage* nested_msg = NULL;
   // Note: no string: reflection API only supports releasing submessages.
@@ -390,12 +439,13 @@
     const Reflection* r = arena_message->GetReflection();
     const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
         "optional_nested_message");
-    nested_msg = dynamic_cast<TestAllTypes::NestedMessage*>(
+    nested_msg = static_cast<TestAllTypes::NestedMessage*>(
         r->ReleaseMessage(arena_message, f));
   }
   EXPECT_EQ(42, nested_msg->bb());
   delete nested_msg;
 }
+#endif  // !GOOGLE_PROTOBUF_NO_RTTI
 
 TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
   Arena arena;
@@ -671,6 +721,57 @@
   }
 }
 
+TEST(ArenaTest, UnsafeArenaRelease) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+
+  string* s = new string("test string");
+  message->unsafe_arena_set_allocated_optional_string(s);
+  EXPECT_TRUE(message->has_optional_string());
+  EXPECT_EQ("test string", message->optional_string());
+  s = message->unsafe_arena_release_optional_string();
+  EXPECT_FALSE(message->has_optional_string());
+  delete s;
+
+  s = new string("test string");
+  message->unsafe_arena_set_allocated_oneof_string(s);
+  EXPECT_TRUE(message->has_oneof_string());
+  EXPECT_EQ("test string", message->oneof_string());
+  s = message->unsafe_arena_release_oneof_string();
+  EXPECT_FALSE(message->has_oneof_string());
+  delete s;
+}
+
+TEST(ArenaTest, ArenaOneofReflection) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+  const Descriptor* desc = message->GetDescriptor();
+  const Reflection* refl = message->GetReflection();
+
+  const FieldDescriptor* string_field = desc->FindFieldByName(
+      "oneof_string");
+  const FieldDescriptor* msg_field = desc->FindFieldByName(
+      "oneof_nested_message");
+  const OneofDescriptor* oneof = desc->FindOneofByName(
+      "oneof_field");
+
+  refl->SetString(message, string_field, "Test value");
+  EXPECT_TRUE(refl->HasOneof(*message, oneof));
+  refl->ClearOneof(message, oneof);
+  EXPECT_FALSE(refl->HasOneof(*message, oneof));
+
+  Message* submsg = refl->MutableMessage(message, msg_field);
+  EXPECT_TRUE(refl->HasOneof(*message, oneof));
+  refl->ClearOneof(message, oneof);
+  EXPECT_FALSE(refl->HasOneof(*message, oneof));
+  refl->MutableMessage(message, msg_field);
+  EXPECT_TRUE(refl->HasOneof(*message, oneof));
+  submsg = refl->ReleaseMessage(message, msg_field);
+  EXPECT_FALSE(refl->HasOneof(*message, oneof));
+  EXPECT_TRUE(submsg->GetArena() == NULL);
+  delete submsg;
+}
+
 namespace {
 void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
   // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
@@ -746,27 +847,6 @@
       protobuf_unittest::optional_nested_message_extension)->set_bb(42);
 }
 
-class NoHeapChecker {
- public:
-  NoHeapChecker() {
-    capture_alloc.Hook();
-  }
-  ~NoHeapChecker() {
-    capture_alloc.Unhook();
-    EXPECT_EQ(0, capture_alloc.alloc_count());
-    EXPECT_EQ(0, capture_alloc.free_count());
-  }
- private:
-  class NewDeleteCapture {
-   public:
-    // TOOD(xiaofeng): Implement this for opensource protobuf.
-    void Hook() {}
-    void Unhook() {}
-    int alloc_count() { return 0; }
-    int free_count() { return 0; }
-  } capture_alloc;
-};
-
 TEST(ArenaTest, RepeatedFieldOnArena) {
   // Preallocate an initial arena block to avoid mallocs during hooked region.
   std::vector<char> arena_block(1024 * 1024);
@@ -776,7 +856,7 @@
   Arena arena(options);
 
   {
-    NoHeapChecker no_heap;
+    internal::NoHeapChecker no_heap;
 
     // Fill some repeated fields on the arena to test for leaks. Also verify no
     // memory allocations.
@@ -846,6 +926,7 @@
 }
 
 
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
 TEST(ArenaTest, MutableMessageReflection) {
   Arena arena;
   TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -853,7 +934,7 @@
   const Descriptor* d = message->GetDescriptor();
   const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
   TestAllTypes::NestedMessage* submessage =
-      dynamic_cast<TestAllTypes::NestedMessage*>(
+      static_cast<TestAllTypes::NestedMessage*>(
           r->MutableMessage(message, field));
   TestAllTypes::NestedMessage* submessage_expected =
       message->mutable_optional_nested_message();
@@ -862,13 +943,14 @@
   EXPECT_EQ(&arena, submessage->GetArena());
 
   const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message");
-  submessage = dynamic_cast<TestAllTypes::NestedMessage*>(
+  submessage = static_cast<TestAllTypes::NestedMessage*>(
       r->MutableMessage(message, oneof_field));
   submessage_expected = message->mutable_oneof_nested_message();
 
   EXPECT_EQ(submessage_expected, submessage);
   EXPECT_EQ(&arena, submessage->GetArena());
 }
+#endif  // !GOOGLE_PROTOBUF_NO_RTTI
 
 
 namespace {
@@ -911,7 +993,7 @@
   arena.Reset();
 }
 
-
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
 // Test construction on an arena via generic MessageLite interface. We should be
 // able to successfully deserialize on the arena without incurring heap
 // allocations, i.e., everything should still be arena-allocation-aware.
@@ -921,8 +1003,7 @@
   options.initial_block = &arena_block[0];
   options.initial_block_size = arena_block.size();
   Arena arena(options);
-  const google::protobuf::MessageLite* prototype = dynamic_cast<
-      const google::protobuf::MessageLite*>(&TestAllTypes::default_instance());
+  const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance();
 
   TestAllTypes initial_message;
   FillArenaAwareFields(&initial_message);
@@ -935,13 +1016,13 @@
     EXPECT_TRUE(generic_message != NULL);
     EXPECT_EQ(&arena, generic_message->GetArena());
     EXPECT_TRUE(generic_message->ParseFromString(serialized));
-    TestAllTypes* deserialized = dynamic_cast<TestAllTypes*>(generic_message);
-    EXPECT_TRUE(deserialized != NULL);
+    TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
     EXPECT_EQ(42, deserialized->optional_int32());
   }
 
   arena.Reset();
 }
+#endif  // !GOOGLE_PROTOBUF_NO_RTTI
 
 
 // RepeatedField should support non-POD types, and invoke constructors and
@@ -963,16 +1044,23 @@
   }
 }
 
-TEST(ArenaTest, SpaceUsed) {
+// Align n to next multiple of 8
+namespace {
+uint64 Align8(uint64 n) { return (n + 7) & -8; }
+}  // namespace
+
+TEST(ArenaTest, SpaceAllocated_and_Used) {
   ArenaOptions options;
   options.start_block_size = 256;
   options.max_block_size = 8192;
   Arena arena_1(options);
+  EXPECT_EQ(0, arena_1.SpaceAllocated());
   EXPECT_EQ(0, arena_1.SpaceUsed());
   EXPECT_EQ(0, arena_1.Reset());
   ::google::protobuf::Arena::CreateArray<char>(&arena_1, 320);
   // Arena will allocate slightly more than 320 for the block headers.
-  EXPECT_LE(320, arena_1.SpaceUsed());
+  EXPECT_LE(320, arena_1.SpaceAllocated());
+  EXPECT_EQ(Align8(320), arena_1.SpaceUsed());
   EXPECT_LE(320, arena_1.Reset());
 
   // Test with initial block.
@@ -980,20 +1068,25 @@
   options.initial_block = &arena_block[0];
   options.initial_block_size = arena_block.size();
   Arena arena_2(options);
-  EXPECT_EQ(1024, arena_2.SpaceUsed());
+  EXPECT_EQ(1024, arena_2.SpaceAllocated());
+  EXPECT_EQ(0, arena_2.SpaceUsed());
   EXPECT_EQ(1024, arena_2.Reset());
   ::google::protobuf::Arena::CreateArray<char>(&arena_2, 55);
-  EXPECT_EQ(1024, arena_2.SpaceUsed());
+  EXPECT_EQ(1024, arena_2.SpaceAllocated());
+  EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
   EXPECT_EQ(1024, arena_2.Reset());
 
   // Reset options to test doubling policy explicitly.
   options.initial_block = NULL;
   options.initial_block_size = 0;
   Arena arena_3(options);
+  EXPECT_EQ(0, arena_3.SpaceUsed());
   ::google::protobuf::Arena::CreateArray<char>(&arena_3, 190);
-  EXPECT_EQ(256, arena_3.SpaceUsed());
+  EXPECT_EQ(256, arena_3.SpaceAllocated());
+  EXPECT_EQ(Align8(190), arena_3.SpaceUsed());
   ::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
-  EXPECT_EQ(256 + 512, arena_3.SpaceUsed());
+  EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
+  EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed());
   EXPECT_EQ(256 + 512, arena_3.Reset());
 }
 
@@ -1005,5 +1098,76 @@
   }
 }
 
+TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) {
+  ::google::protobuf::Arena arena;
+  ArenaMessage* message = Arena::CreateMessage<ArenaMessage>(&arena);
+  const ArenaMessage* const_pointer_to_message = message;
+  EXPECT_EQ(&arena, Arena::GetArena(message));
+  EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message));
+}
+
+TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
+  ArenaMessage message;
+  const ArenaMessage* const_pointer_to_message = &message;
+  EXPECT_EQ(NULL, Arena::GetArena(&message));
+  EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
+}
+
+// A helper utility class to only contain static hook functions, some
+// counters to be used to verify the counters have been called and a cookie
+// value to be verified.
+class ArenaHooksTestUtil {
+ public:
+  static void* on_init(::google::protobuf::Arena* arena) {
+    ++num_init;
+    int* cookie = new int(kCookieValue);
+    return static_cast<void*>(cookie);
+  }
+
+  static void on_reset(::google::protobuf::Arena* arena, void* cookie,
+                       uint64 space_used) {
+    ++num_reset;
+    int cookie_value = *static_cast<int*>(cookie);
+    EXPECT_EQ(kCookieValue, cookie_value);
+  }
+
+  static void on_destruction(::google::protobuf::Arena* arena, void* cookie,
+                             uint64 space_used) {
+    ++num_destruct;
+    int cookie_value = *static_cast<int*>(cookie);
+    EXPECT_EQ(kCookieValue, cookie_value);
+    delete static_cast<int*>(cookie);
+  }
+
+  static const int kCookieValue = 999;
+  static uint32 num_init;
+  static uint32 num_reset;
+  static uint32 num_destruct;
+};
+uint32 ArenaHooksTestUtil::num_init = 0;
+uint32 ArenaHooksTestUtil::num_reset = 0;
+uint32 ArenaHooksTestUtil::num_destruct = 0;
+const int ArenaHooksTestUtil::kCookieValue;
+
+// Test the hooks are correctly called and that the cookie is passed.
+TEST(ArenaTest, ArenaHooksSanity) {
+  ::google::protobuf::ArenaOptions options;
+  options.on_arena_init = ArenaHooksTestUtil::on_init;
+  options.on_arena_reset = ArenaHooksTestUtil::on_reset;
+  options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
+
+  // Scope for defining the arena
+  {
+    ::google::protobuf::Arena arena(options);
+    EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
+
+    arena.Reset();
+    arena.Reset();
+    EXPECT_EQ(2, ArenaHooksTestUtil::num_reset);
+  }
+  EXPECT_EQ(3, ArenaHooksTestUtil::num_reset);
+  EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct);
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 4095b3c..567238a 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -151,7 +151,7 @@
   if (path.empty()) return true;
 
   if (access(path.c_str(), F_OK) == -1) {
-    cerr << path << ": " << strerror(errno) << endl;
+    std::cerr << path << ": " << strerror(errno) << std::endl;
     return false;
   } else {
     return true;
@@ -170,8 +170,8 @@
     path_so_far += parts[i];
     if (mkdir(path_so_far.c_str(), 0777) != 0) {
       if (errno != EEXIST) {
-        cerr << filename << ": while trying to create directory "
-             << path_so_far << ": " << strerror(errno) << endl;
+        std::cerr << filename << ": while trying to create directory "
+                  << path_so_far << ": " << strerror(errno) << std::endl;
         return false;
       }
     }
@@ -200,9 +200,9 @@
     if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
         tree_ != NULL &&
         tree_->VirtualFileToDiskFile(filename, &dfile)) {
-      cerr << dfile;
+      std::cerr << dfile;
     } else {
-      cerr << filename;
+      std::cerr << filename;
     }
 
     // Users typically expect 1-based line/column numbers, so we add 1
@@ -211,15 +211,16 @@
       // Allow for both GCC- and Visual-Studio-compatible output.
       switch (format_) {
         case CommandLineInterface::ERROR_FORMAT_GCC:
-          cerr << ":" << (line + 1) << ":" << (column + 1);
+          std::cerr << ":" << (line + 1) << ":" << (column + 1);
           break;
         case CommandLineInterface::ERROR_FORMAT_MSVS:
-          cerr << "(" << (line + 1) << ") : error in column=" << (column + 1);
+          std::cerr << "(" << (line + 1)
+                    << ") : error in column=" << (column + 1);
           break;
       }
     }
 
-    cerr << ": " << message << endl;
+    std::cerr << ": " << message << std::endl;
   }
 
   // implements io::ErrorCollector -----------------------------------
@@ -347,7 +348,7 @@
 
     if (file_descriptor < 0) {
       int error = errno;
-      cerr << filename << ": " << strerror(error);
+      std::cerr << filename << ": " << strerror(error);
       return false;
     }
 
@@ -371,9 +372,9 @@
 
         if (write_result < 0) {
           int error = errno;
-          cerr << filename << ": write: " << strerror(error);
+          std::cerr << filename << ": write: " << strerror(error);
         } else {
-          cerr << filename << ": write() returned zero?" << endl;
+          std::cerr << filename << ": write() returned zero?" << std::endl;
         }
         return false;
       }
@@ -384,7 +385,7 @@
 
     if (close(file_descriptor) != 0) {
       int error = errno;
-      cerr << filename << ": close: " << strerror(error);
+      std::cerr << filename << ": close: " << strerror(error);
       return false;
     }
   }
@@ -407,7 +408,7 @@
 
   if (file_descriptor < 0) {
     int error = errno;
-    cerr << filename << ": " << strerror(error);
+    std::cerr << filename << ": " << strerror(error);
     return false;
   }
 
@@ -423,11 +424,11 @@
   zip_writer.WriteDirectory();
 
   if (stream.GetErrno() != 0) {
-    cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+    std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
   }
 
   if (!stream.Close()) {
-    cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+    std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
   }
 
   return true;
@@ -500,7 +501,8 @@
       if (append_mode_) {
         (*map_slot)->append(data_);
       } else {
-        cerr << filename_ << ": Tried to write the same file twice." << endl;
+        std::cerr << filename_ << ": Tried to write the same file twice."
+                  << std::endl;
         directory_->had_error_ = true;
       }
       return;
@@ -518,8 +520,9 @@
 
     // Find the file we are going to insert into.
     if (*map_slot == NULL) {
-      cerr << filename_ << ": Tried to insert into file that doesn't exist."
-           << endl;
+      std::cerr << filename_
+                << ": Tried to insert into file that doesn't exist."
+                << std::endl;
       directory_->had_error_ = true;
       return;
     }
@@ -531,8 +534,8 @@
     string::size_type pos = target->find(magic_string);
 
     if (pos == string::npos) {
-      cerr << filename_ << ": insertion point \"" << insertion_point_
-           << "\" not found." << endl;
+      std::cerr << filename_ << ": insertion point \"" << insertion_point_
+                << "\" not found." << std::endl;
       directory_->had_error_ = true;
       return;
     }
@@ -810,27 +813,31 @@
         input_files_[i] = virtual_file;
         break;
       case DiskSourceTree::SHADOWED:
-        cerr << input_files_[i] << ": Input is shadowed in the --proto_path "
-                "by \"" << shadowing_disk_file << "\".  Either use the latter "
-                "file as your input or reorder the --proto_path so that the "
-                "former file's location comes first." << endl;
+        std::cerr << input_files_[i]
+                  << ": Input is shadowed in the --proto_path by \""
+                  << shadowing_disk_file
+                  << "\".  Either use the latter file as your input or reorder "
+                     "the --proto_path so that the former file's location "
+                     "comes first." << std::endl;
         return false;
       case DiskSourceTree::CANNOT_OPEN:
-        cerr << input_files_[i] << ": " << strerror(errno) << endl;
+        std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl;
         return false;
       case DiskSourceTree::NO_MAPPING:
         // First check if the file exists at all.
         if (access(input_files_[i].c_str(), F_OK) < 0) {
           // File does not even exist.
-          cerr << input_files_[i] << ": " << strerror(ENOENT) << endl;
+          std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
         } else {
-          cerr << input_files_[i] << ": File does not reside within any path "
-                  "specified using --proto_path (or -I).  You must specify a "
-                  "--proto_path which encompasses this file.  Note that the "
-                  "proto_path must be an exact prefix of the .proto file "
-                  "names -- protoc is too dumb to figure out when two paths "
-                  "(e.g. absolute and relative) are equivalent (it's harder "
-                  "than you think)." << endl;
+          std::cerr
+              << input_files_[i]
+              << ": File does not reside within any path "
+                 "specified using --proto_path (or -I).  You must specify a "
+                 "--proto_path which encompasses this file.  Note that the "
+                 "proto_path must be an exact prefix of the .proto file "
+                 "names -- protoc is too dumb to figure out when two paths "
+                 "(e.g. absolute and relative) are equivalent (it's harder "
+                 "than you think)." << std::endl;
         }
         return false;
     }
@@ -850,9 +857,10 @@
     if (ParseArgument(argv[i], &name, &value)) {
       // Returned true => Use the next argument as the flag value.
       if (i + 1 == argc || argv[i+1][0] == '-') {
-        cerr << "Missing value for flag: " << name << endl;
+        std::cerr << "Missing value for flag: " << name << std::endl;
         if (name == "--decode") {
-          cerr << "To decode an unknown message, use --decode_raw." << endl;
+          std::cerr << "To decode an unknown message, use --decode_raw."
+                    << std::endl;
         }
         return PARSE_ARGUMENT_FAIL;
       } else {
@@ -877,15 +885,16 @@
   // Check some errror cases.
   bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
   if (decoding_raw && !input_files_.empty()) {
-    cerr << "When using --decode_raw, no input files should be given." << endl;
+    std::cerr << "When using --decode_raw, no input files should be given."
+              << std::endl;
     return PARSE_ARGUMENT_FAIL;
   } else if (!decoding_raw && input_files_.empty()) {
-    cerr << "Missing input file." << endl;
+    std::cerr << "Missing input file." << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
   if (mode_ == MODE_COMPILE && output_directives_.empty() &&
       descriptor_set_name_.empty()) {
-    cerr << "Missing output directives." << endl;
+    std::cerr << "Missing output directives." << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
   if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) {
@@ -898,12 +907,12 @@
     return PARSE_ARGUMENT_FAIL;
   }
   if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
-    cerr << "--include_imports only makes sense when combined with "
-            "--descriptor_set_out." << endl;
+    std::cerr << "--include_imports only makes sense when combined with "
+                 "--descriptor_set_out." << std::endl;
   }
   if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
-    cerr << "--include_source_info only makes sense when combined with "
-            "--descriptor_set_out." << endl;
+    std::cerr << "--include_source_info only makes sense when combined with "
+                 "--descriptor_set_out." << std::endl;
   }
 
   return PARSE_ARGUMENT_DONE_AND_CONTINUE;
@@ -976,10 +985,12 @@
   if (name.empty()) {
     // Not a flag.  Just a filename.
     if (value.empty()) {
-      cerr << "You seem to have passed an empty string as one of the "
-              "arguments to " << executable_name_ << ".  This is actually "
-              "sort of hard to do.  Congrats.  Unfortunately it is not valid "
-              "input so the program is going to die now." << endl;
+      std::cerr
+          << "You seem to have passed an empty string as one of the "
+             "arguments to " << executable_name_
+          << ".  This is actually "
+             "sort of hard to do.  Congrats.  Unfortunately it is not valid "
+             "input so the program is going to die now." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
 
@@ -1006,14 +1017,16 @@
       }
 
       if (disk_path.empty()) {
-        cerr << "--proto_path passed empty directory name.  (Use \".\" for "
-                "current directory.)" << endl;
+        std::cerr
+            << "--proto_path passed empty directory name.  (Use \".\" for "
+               "current directory.)" << std::endl;
         return PARSE_ARGUMENT_FAIL;
       }
 
       // Make sure disk path exists, warn otherwise.
       if (access(disk_path.c_str(), F_OK) < 0) {
-        cerr << disk_path << ": warning: directory does not exist." << endl;
+        std::cerr << disk_path << ": warning: directory does not exist."
+                  << std::endl;
       }
 
       // Don't use make_pair as the old/default standard library on Solaris
@@ -1024,16 +1037,17 @@
 
   } else if (name == "-o" || name == "--descriptor_set_out") {
     if (!descriptor_set_name_.empty()) {
-      cerr << name << " may only be passed once." << endl;
+      std::cerr << name << " may only be passed once." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     if (value.empty()) {
-      cerr << name << " requires a non-empty value." << endl;
+      std::cerr << name << " requires a non-empty value." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     if (mode_ != MODE_COMPILE) {
-      cerr << "Cannot use --encode or --decode and generate descriptors at the "
-              "same time." << endl;
+      std::cerr
+          << "Cannot use --encode or --decode and generate descriptors at the "
+             "same time." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     descriptor_set_name_ = value;
@@ -1051,14 +1065,14 @@
 
   } else if (name == "--include_imports") {
     if (imports_in_descriptor_set_) {
-      cerr << name << " may only be passed once." << endl;
+      std::cerr << name << " may only be passed once." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     imports_in_descriptor_set_ = true;
 
   } else if (name == "--include_source_info") {
     if (source_info_in_descriptor_set_) {
-      cerr << name << " may only be passed once." << endl;
+      std::cerr << name << " may only be passed once." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     source_info_in_descriptor_set_ = true;
@@ -1069,7 +1083,7 @@
 
   } else if (name == "--version") {
     if (!version_info_.empty()) {
-      cout << version_info_ << endl;
+      std::cout << version_info_ << std::endl;
     }
     cout << "libprotoc "
          << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
@@ -1082,25 +1096,28 @@
   } else if (name == "--encode" || name == "--decode" ||
              name == "--decode_raw") {
     if (mode_ != MODE_COMPILE) {
-      cerr << "Only one of --encode and --decode can be specified." << endl;
+      std::cerr << "Only one of --encode and --decode can be specified."
+                << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
-      cerr << "Cannot use " << name
-           << " and generate code or descriptors at the same time." << endl;
+      std::cerr << "Cannot use " << name
+                << " and generate code or descriptors at the same time."
+                << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
 
     mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
 
     if (value.empty() && name != "--decode_raw") {
-      cerr << "Type name for " << name << " cannot be blank." << endl;
+      std::cerr << "Type name for " << name << " cannot be blank." << std::endl;
       if (name == "--decode") {
-        cerr << "To decode an unknown message, use --decode_raw." << endl;
+        std::cerr << "To decode an unknown message, use --decode_raw."
+                  << std::endl;
       }
       return PARSE_ARGUMENT_FAIL;
     } else if (!value.empty() && name == "--decode_raw") {
-      cerr << "--decode_raw does not take a parameter." << endl;
+      std::cerr << "--decode_raw does not take a parameter." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
 
@@ -1112,13 +1129,13 @@
     } else if (value == "msvs") {
       error_format_ = ERROR_FORMAT_MSVS;
     } else {
-      cerr << "Unknown error format: " << value << endl;
+      std::cerr << "Unknown error format: " << value << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
 
   } else if (name == "--plugin") {
     if (plugin_prefix_.empty()) {
-      cerr << "This compiler does not support plugins." << endl;
+      std::cerr << "This compiler does not support plugins." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
 
@@ -1144,13 +1161,15 @@
 
   } else if (name == "--print_free_field_numbers") {
     if (mode_ != MODE_COMPILE) {
-      cerr << "Cannot use " << name << " and use --encode, --decode or print "
-           << "other info at the same time." << endl;
+      std::cerr << "Cannot use " << name
+                << " and use --encode, --decode or print "
+                << "other info at the same time." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
-      cerr << "Cannot use " << name
-           << " and generate code or descriptors at the same time." << endl;
+      std::cerr << "Cannot use " << name
+                << " and generate code or descriptors at the same time."
+                << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
     mode_ = MODE_PRINT;
@@ -1164,7 +1183,7 @@
       // Check if it's a generator option flag.
       generator_info = FindOrNull(generators_by_option_name_, name);
       if (generator_info == NULL) {
-        cerr << "Unknown flag: " << name << endl;
+        std::cerr << "Unknown flag: " << name << std::endl;
         return PARSE_ARGUMENT_FAIL;
       } else {
         string* parameters = &generator_parameters_[generator_info->flag_name];
@@ -1176,8 +1195,8 @@
     } else {
       // It's an output flag.  Add it to the output directives.
       if (mode_ != MODE_COMPILE) {
-        cerr << "Cannot use --encode, --decode or print .proto info and "
-                "generate code at the same time." << endl;
+        std::cerr << "Cannot use --encode, --decode or print .proto info and "
+                     "generate code at the same time." << std::endl;
         return PARSE_ARGUMENT_FAIL;
       }
 
@@ -1209,7 +1228,7 @@
 
 void CommandLineInterface::PrintHelpText() {
   // Sorry for indentation here; line wrapping would be uglier.
-  cerr <<
+  std::cerr <<
 "Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
 "Parse PROTO_FILES and generate output based on the options given:\n"
 "  -IPATH, --proto_path=PATH   Specify the directory in which to search for\n"
@@ -1253,9 +1272,9 @@
 "                              defined in the given proto files. Groups share\n"
 "                              the same field number space with the parent \n"
 "                              message. Extension ranges are counted as \n"
-"                              occupied fields numbers."  << endl;
+"                              occupied fields numbers."  << std::endl;
   if (!plugin_prefix_.empty()) {
-    cerr <<
+    std::cerr <<
 "  --plugin=EXECUTABLE         Specifies a plugin executable to use.\n"
 "                              Normally, protoc searches the PATH for\n"
 "                              plugins, but you may specify additional\n"
@@ -1263,7 +1282,7 @@
 "                              Additionally, EXECUTABLE may be of the form\n"
 "                              NAME=PATH, in which case the given plugin name\n"
 "                              is mapped to the given executable even if\n"
-"                              the executable's own name differs." << endl;
+"                              the executable's own name differs." << std::endl;
   }
 
   for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
@@ -1271,9 +1290,9 @@
     // FIXME(kenton):  If the text is long enough it will wrap, which is ugly,
     //   but fixing this nicely (e.g. splitting on spaces) is probably more
     //   trouble than it's worth.
-    cerr << "  " << iter->first << "=OUT_DIR "
-         << string(19 - iter->first.size(), ' ')  // Spaces for alignment.
-         << iter->second.help_text << endl;
+    std::cerr << "  " << iter->first << "=OUT_DIR "
+              << string(19 - iter->first.size(), ' ')  // Spaces for alignment.
+              << iter->second.help_text << std::endl;
   }
 }
 
@@ -1296,7 +1315,7 @@
     if (!GeneratePluginOutput(parsed_files, plugin_name,
                               output_directive.parameter,
                               generator_context, &error)) {
-      cerr << output_directive.name << ": " << error << endl;
+      std::cerr << output_directive.name << ": " << error << std::endl;
       return false;
     }
   } else {
@@ -1312,8 +1331,8 @@
       if (!output_directive.generator->Generate(parsed_files[i], parameters,
                                                 generator_context, &error)) {
         // Generator returned an error.
-        cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
-             << error << endl;
+        std::cerr << output_directive.name << ": " << parsed_files[i]->name()
+                  << ": " << error << std::endl;
         return false;
       }
     }
@@ -1475,7 +1494,7 @@
   // Look up the type.
   const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
   if (type == NULL) {
-    cerr << "Type not defined: " << codec_type_ << endl;
+    std::cerr << "Type not defined: " << codec_type_ << std::endl;
     return false;
   }
 
@@ -1501,32 +1520,32 @@
     parser.AllowPartialMessage(true);
 
     if (!parser.Parse(&in, message.get())) {
-      cerr << "Failed to parse input." << endl;
+      std::cerr << "Failed to parse input." << std::endl;
       return false;
     }
   } else {
     // Input is binary.
     if (!message->ParsePartialFromZeroCopyStream(&in)) {
-      cerr << "Failed to parse input." << endl;
+      std::cerr << "Failed to parse input." << std::endl;
       return false;
     }
   }
 
   if (!message->IsInitialized()) {
-    cerr << "warning:  Input message is missing required fields:  "
-         << message->InitializationErrorString() << endl;
+    std::cerr << "warning:  Input message is missing required fields:  "
+              << message->InitializationErrorString() << std::endl;
   }
 
   if (mode_ == MODE_ENCODE) {
     // Output is binary.
     if (!message->SerializePartialToZeroCopyStream(&out)) {
-      cerr << "output: I/O error." << endl;
+      std::cerr << "output: I/O error." << std::endl;
       return false;
     }
   } else {
     // Output is text.
     if (!TextFormat::Print(*message, &out)) {
-      cerr << "output: I/O error." << endl;
+      std::cerr << "output: I/O error." << std::endl;
       return false;
     }
   }
@@ -1568,12 +1587,14 @@
 
   io::FileOutputStream out(fd);
   if (!file_set.SerializeToZeroCopyStream(&out)) {
-    cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
+    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+              << std::endl;
     out.Close();
     return false;
   }
   if (!out.Close()) {
-    cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
+    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+              << std::endl;
     return false;
   }
 
@@ -1692,7 +1713,7 @@
   if (next_free_number <= FieldDescriptor::kMaxNumber) {
     StringAppendF(&output, " %d-INF", next_free_number);
   }
-  cout << output << endl;
+  std::cout << output << std::endl;
 }
 
 }  // namespace
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 2aba68b..2b26f3b 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -64,6 +64,9 @@
 #include <gtest/gtest.h>
 
 
+// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
+// which case tcmalloc will print warnings that fail the plugin tests.
+#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -1746,4 +1749,6 @@
 
 }  // namespace compiler
 }  // namespace protobuf
+
+#endif  // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
 }  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 4878819..13ed0b6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -98,7 +98,8 @@
                           &actual_contents, true));
     EXPECT_TRUE(actual_contents == *expected_contents)
       << physical_filename << " needs to be regenerated.  Please run "
-         "generate_descriptor_proto.sh and add this file "
+         "google/protobuf/compiler/release_compiler.sh and "
+         "generate_descriptor_proto.sh. Then add this file "
          "to your CL.";
   }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 3ce1f12..0404b73 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -47,7 +47,7 @@
 
 namespace {
 // The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
-// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
+// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
 // generation of the GOOGLE_ARRAYSIZE constant.
 bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
   int32 max_value = descriptor->value(0)->number();
@@ -56,7 +56,7 @@
       max_value = descriptor->value(i)->number();
     }
   }
-  return max_value != kint32max;
+  return max_value != ::google::protobuf::kint32max;
 }
 }  // namespace
 
@@ -153,9 +153,12 @@
 
 void EnumGenerator::
 GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+  printer->Print(
+      "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
+      "{};\n",
+      "classname", ClassName(descriptor_, true));
   if (HasDescriptorMethods(descriptor_->file())) {
     printer->Print(
-      "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n"
       "template <>\n"
       "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
       "  return $classname$_descriptor();\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 1792613..7498970 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -76,23 +76,26 @@
 void EnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline $type$ $name$() const$deprecation$;\n"
-    "inline void set_$name$($type$ value)$deprecation$;\n");
+    "$type$ $name$() const$deprecation$;\n"
+    "void set_$name$($type$ value)$deprecation$;\n");
 }
 
 void EnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return static_cast< $type$ >($name$_);\n"
     "}\n"
-    "inline void $classname$::set_$name$($type$ value) {\n");
+    "$inline$ void $classname$::set_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables_,
+    printer->Print(variables,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables_,
+  printer->Print(variables,
     "  $set_hasbit$\n"
     "  $name$_ = value;\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -181,21 +184,24 @@
 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
 
 void EnumOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  if (has_$name$()) {\n"
     "    return static_cast< $type$ >($oneof_prefix$$name$_);\n"
     "  }\n"
     "  return static_cast< $type$ >($default$);\n"
     "}\n"
-    "inline void $classname$::set_$name$($type$ value) {\n");
+    "$inline$ void $classname$::set_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables_,
+    printer->Print(variables,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables_,
+  printer->Print(variables,
     "  if (!has_$name$()) {\n"
     "    clear_$oneof_name$();\n"
     "    set_has_$name$();\n"
@@ -246,46 +252,49 @@
 void RepeatedEnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline $type$ $name$(int index) const$deprecation$;\n"
-    "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
-    "inline void add_$name$($type$ value)$deprecation$;\n");
+    "$type$ $name$(int index) const$deprecation$;\n"
+    "void set_$name$(int index, $type$ value)$deprecation$;\n"
+    "void add_$name$($type$ value)$deprecation$;\n");
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
-    "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
+    "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+    "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
 }
 
 void RepeatedEnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$(int index) const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return static_cast< $type$ >($name$_.Get(index));\n"
     "}\n"
-    "inline void $classname$::set_$name$(int index, $type$ value) {\n");
+    "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables_,
+    printer->Print(variables,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables_,
+  printer->Print(variables,
     "  $name$_.Set(index, value);\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "}\n"
-    "inline void $classname$::add_$name$($type$ value) {\n");
+    "$inline$ void $classname$::add_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables_,
+    printer->Print(variables,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables_,
+  printer->Print(variables,
     "  $name$_.Add(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
     "}\n");
-  printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedField<int>&\n"
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedField<int>&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "inline ::google::protobuf::RepeatedField<int>*\n"
+    "$inline$ ::google::protobuf::RepeatedField<int>*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
@@ -344,20 +353,34 @@
 void RepeatedEnumFieldGenerator::
 GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
   if (!descriptor_->options().packed()) {
-    // We use a non-inlined implementation in this case, since this path will
-    // rarely be executed.
-    printer->Print(variables_,
-      "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
-      "       input,\n");
+      // This path is rarely executed, so we use a non-inlined implementation.
     if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
       printer->Print(variables_,
-      "       NULL,\n");
+        "DO_((::google::protobuf::internal::"
+                    "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+        "       input,\n"
+        "       $number$,\n"
+        "       NULL,\n"
+        "       NULL,\n"
+        "       this->mutable_$name$())));\n");
+    } else if (UseUnknownFieldSet(descriptor_->file())) {
+      printer->Print(variables_,
+        "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
+        "       input,\n"
+        "       $number$,\n"
+        "       $type$_IsValid,\n"
+        "       mutable_unknown_fields(),\n"
+        "       this->mutable_$name$())));\n");
     } else {
       printer->Print(variables_,
-      "       &$type$_IsValid,\n");
+        "DO_((::google::protobuf::internal::"
+                     "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+        "       input,\n"
+        "       $number$,\n"
+        "       $type$_IsValid,\n"
+        "       &unknown_fields_stream,\n"
+        "       this->mutable_$name$())));\n");
     }
-    printer->Print(variables_,
-      "       this->mutable_$name$())));\n");
   } else {
     printer->Print(variables_,
       "::google::protobuf::uint32 length;\n"
@@ -376,6 +399,16 @@
       printer->Print(variables_,
       "  if ($type$_IsValid(value)) {\n"
       "    add_$name$(static_cast< $type$ >(value));\n"
+      "  } else {\n");
+      if (UseUnknownFieldSet(descriptor_->file())) {
+        printer->Print(variables_,
+        "    mutable_unknown_fields()->AddVarint($number$, value);\n");
+      } else {
+        printer->Print(variables_,
+        "    unknown_fields_stream.WriteVarint32(tag);\n"
+        "    unknown_fields_stream.WriteVarint32(value);\n");
+      }
+      printer->Print(
       "  }\n");
     }
     printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index def2b23..5b1d01e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -53,7 +53,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +79,8 @@
   ~EnumOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
@@ -96,7 +98,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index c37fe0b..cd2b6b7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -89,7 +89,7 @@
   // Generate inline definitions of accessor functions for this field.
   // These are placed inside the header after all class definitions.
   virtual void GenerateInlineAccessorDefinitions(
-    io::Printer* printer) const = 0;
+    io::Printer* printer, bool is_inline) const = 0;
 
   // Generate definitions of accessors that aren't inlined.  These are
   // placed somewhere in the .cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index fae4df4..a98c7d9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -136,8 +136,11 @@
   printer->Print(
     "#include <google/protobuf/arena.h>\n"
     "#include <google/protobuf/arenastring.h>\n"
-    "#include <google/protobuf/generated_message_util.h>\n"
-    "#include <google/protobuf/metadata.h>\n");
+    "#include <google/protobuf/generated_message_util.h>\n");
+  if (UseUnknownFieldSet(file_)) {
+    printer->Print(
+      "#include <google/protobuf/metadata.h>\n");
+  }
   if (file_->message_type_count() > 0) {
     if (HasDescriptorMethods(file_)) {
       printer->Print(
@@ -152,13 +155,24 @@
     "#include <google/protobuf/extension_set.h>\n");
   if (HasMapFields(file_)) {
     printer->Print(
-      "#include <google/protobuf/map.h>\n"
-      "#include <google/protobuf/map_field_inl.h>\n");
+        "#include <google/protobuf/map.h>\n");
+    if (HasDescriptorMethods(file_)) {
+      printer->Print(
+          "#include <google/protobuf/map_field_inl.h>\n");
+    } else {
+      printer->Print(
+          "#include <google/protobuf/map_field_lite.h>\n");
+    }
   }
 
-  if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
-    printer->Print(
-      "#include <google/protobuf/generated_enum_reflection.h>\n");
+  if (HasEnumDefinitions(file_)) {
+    if (HasDescriptorMethods(file_)) {
+      printer->Print(
+          "#include <google/protobuf/generated_enum_reflection.h>\n");
+    } else {
+      printer->Print(
+          "#include <google/protobuf/generated_enum_util.h>\n");
+    }
   }
 
   if (HasGenericServices(file_)) {
@@ -272,15 +286,17 @@
   printer->Print(kThickSeparator);
   printer->Print("\n");
 
-
+  printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
   // Generate class inline methods.
   for (int i = 0; i < file_->message_type_count(); i++) {
     if (i > 0) {
       printer->Print(kThinSeparator);
       printer->Print("\n");
     }
-    message_generators_[i]->GenerateInlineMethods(printer);
+    message_generators_[i]->GenerateInlineMethods(printer,
+                                                  /* is_inline = */ true);
   }
+  printer->Print("#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
 
   printer->Print(
     "\n"
@@ -290,7 +306,7 @@
   GenerateNamespaceClosers(printer);
 
   // Emit GetEnumDescriptor specializations into google::protobuf namespace:
-  if (HasDescriptorMethods(file_)) {
+  if (HasEnumDefinitions(file_)) {
     // The SWIG conditional is to avoid a null-pointer dereference
     // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
     //   namespace X { void Y<Z::W>(); }
@@ -417,6 +433,12 @@
     printer->Print(kThickSeparator);
     printer->Print("\n");
     message_generators_[i]->GenerateClassMethods(printer);
+
+    printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+    // Generate class inline methods.
+    message_generators_[i]->GenerateInlineMethods(printer,
+                                                  /* is_inline = */ false);
+    printer->Print("#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
   }
 
   if (HasGenericServices(file_)) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 28c4dd5..237278d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -352,9 +352,7 @@
     } else {
       // Not alphanumeric.  To avoid any possibility of name conflicts we
       // use the hex code for the character.
-      result.push_back('_');
-      char buffer[kFastToBufferSize];
-      result.append(FastHexToBuffer(static_cast<uint8>(filename[i]), buffer));
+      StrAppend(&result, "_", ToHex(static_cast<uint8>(filename[i])));
     }
   }
   return result;
@@ -508,6 +506,13 @@
   return false;
 }
 
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
+  GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
+  // Open-source protobuf release only supports STRING ctype.
+  return FieldOptions::STRING;
+
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index e60fa7c..c7bb8f9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -211,6 +211,10 @@
 // Returns true if the field's CPPTYPE is string or message.
 bool IsStringOrMessage(const FieldDescriptor* field);
 
+// For a string field, returns the effective ctype.  If the actual ctype is
+// not supported, returns the default of STRING.
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field);
+
 string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
 
 inline bool HasFieldPresence(const FileDescriptor* file) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 0154eeb..8c38db2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/compiler/cpp/cpp_map_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -72,14 +73,21 @@
       (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
       (*variables)["wrapper"] = "EntryWrapper";
   }
-  (*variables)["key_type"] =
-      "::google::protobuf::FieldDescriptor::TYPE_" +
+  (*variables)["key_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
       ToUpper(DeclaredTypeMethodName(key->type()));
-  (*variables)["val_type"] =
-      "::google::protobuf::FieldDescriptor::TYPE_" +
+  (*variables)["val_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
       ToUpper(DeclaredTypeMethodName(val->type()));
   (*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
-  (*variables)["number"] = Int32ToString(descriptor->number());
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+
+  if (HasDescriptorMethods(descriptor->file())) {
+    (*variables)["lite"] = "";
+  } else {
+    (*variables)["lite"] = "Lite";
+  }
 
   if (!IsProto3Field(descriptor) &&
       val->type() == FieldDescriptor::TYPE_ENUM) {
@@ -102,33 +110,40 @@
 void MapFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-      "typedef ::google::protobuf::internal::MapEntry<\n"
+      "typedef ::google::protobuf::internal::MapEntryLite<\n"
       "    $key_cpp$, $val_cpp$,\n"
-      "    $key_type$,\n"
-      "    $val_type$, $default_enum_value$>\n"
+      "    $key_wire_type$,\n"
+      "    $val_wire_type$,\n"
+      "    $default_enum_value$ >\n"
       "    $map_classname$;\n"
-      "::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$,"
-      "$key_type$, $val_type$, $default_enum_value$ > $name$_;\n");
+      "::google::protobuf::internal::MapField$lite$<\n"
+      "    $key_cpp$, $val_cpp$,\n"
+      "    $key_wire_type$,\n"
+      "    $val_wire_type$,\n"
+      "    $default_enum_value$ > $name$_;\n");
 }
 
 void MapFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-      "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
       "    $name$() const$deprecation$;\n"
-      "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
       "    mutable_$name$()$deprecation$;\n");
 }
 
 void MapFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-      "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+      "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
       "$classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_map:$full_name$)\n"
       "  return $name$_.GetMap();\n"
       "}\n"
-      "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
       "$classname$::mutable_$name$() {\n"
       "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
       "  return $name$_.MutableMap();\n"
@@ -198,11 +213,29 @@
         "  if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
         "    (*mutable_$name$())[entry->key()] =\n"
         "        static_cast<$val_cpp$>(*entry->mutable_value());\n"
-        "  } else {\n"
-        "    mutable_unknown_fields()->AddLengthDelimited($number$, data);\n"
+        "  } else {\n");
+    if (HasDescriptorMethods(descriptor_->file())) {
+      printer->Print(variables_,
+          "    mutable_unknown_fields()"
+          "->AddLengthDelimited($number$, data);\n");
+    } else {
+      printer->Print(variables_,
+          "    unknown_fields_stream.WriteVarint32($tag$);\n"
+          "    unknown_fields_stream.WriteVarint32(data.size());\n"
+          "    unknown_fields_stream.WriteString(data);\n");
+    }
+
+
+    printer->Print(variables_,
         "  }\n"
         "}\n");
   }
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "if (entry->GetArena() != NULL) entry.release();\n");
+  }
 }
 
 void MapFieldGenerator::
@@ -211,12 +244,31 @@
       "{\n"
       "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
       "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "      it = $name$().begin(); it != $name$().end(); ++it) {\n"
+      "      it = $name$().begin(); it != $name$().end(); ++it) {\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "      entry.release();\n"
+        "    }\n");
+  }
+
+  printer->Print(variables_,
       "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
       "    ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
       "        $number$, *entry, output);\n"
-      "  }\n"
-      "}\n");
+      "  }\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "    entry.release();\n"
+        "  }\n");
+  }
+
+  printer->Print("}\n");
 }
 
 void MapFieldGenerator::
@@ -225,13 +277,32 @@
       "{\n"
       "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
       "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "      it = $name$().begin(); it != $name$().end(); ++it) {\n"
+      "      it = $name$().begin(); it != $name$().end(); ++it) {\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "      entry.release();\n"
+        "    }\n");
+  }
+
+  printer->Print(variables_,
       "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
       "    target = ::google::protobuf::internal::WireFormatLite::\n"
       "        Write$declared_type$NoVirtualToArray(\n"
       "            $number$, *entry, target);\n"
-      "  }\n"
-      "}\n");
+      "  }\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "    entry.release();\n"
+        "  }\n");
+  }
+
+  printer->Print("}\n");
 }
 
 void MapFieldGenerator::
@@ -241,12 +312,31 @@
       "{\n"
       "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
       "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "      it = $name$().begin(); it != $name$().end(); ++it) {\n"
+      "      it = $name$().begin(); it != $name$().end(); ++it) {\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "      entry.release();\n"
+        "    }\n");
+  }
+
+  printer->Print(variables_,
       "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
       "    total_size += ::google::protobuf::internal::WireFormatLite::\n"
       "        $declared_type$SizeNoVirtual(*entry);\n"
-      "  }\n"
-      "}\n");
+      "  }\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "    entry.release();\n"
+        "  }\n");
+  }
+
+  printer->Print("}\n");
 }
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index 0ff032f..d27d485 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -50,7 +50,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index e71d35f..bafa36f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -87,8 +87,8 @@
   for (int i = 0; i < descriptor->field_count(); i++) {
     fields[i] = descriptor->field(i);
   }
-  sort(fields, fields + descriptor->field_count(),
-       FieldOrderingByNumber());
+  std::sort(fields, fields + descriptor->field_count(),
+            FieldOrderingByNumber());
   return fields;
 }
 
@@ -253,7 +253,7 @@
   // Sort by preferred location to keep fields as close to their original
   // location as possible.  Using stable_sort ensures that the output is
   // consistent across runs.
-  stable_sort(aligned_to_4.begin(), aligned_to_4.end());
+  std::stable_sort(aligned_to_4.begin(), aligned_to_4.end());
 
   // Now group fields aligned to 4 bytes (or the 4-field groups created above)
   // into pairs, and treat those like a single field aligned to 8 bytes.
@@ -269,7 +269,7 @@
     aligned_to_8.push_back(field_group);
   }
   // Sort by preferred location.
-  stable_sort(aligned_to_8.begin(), aligned_to_8.end());
+  std::stable_sort(aligned_to_8.begin(), aligned_to_8.end());
 
   // Now pull out all the FieldDescriptors in order.
   fields->clear();
@@ -280,10 +280,6 @@
   }
 }
 
-string MessageTypeProtoName(const FieldDescriptor* field) {
-  return field->message_type()->full_name();
-}
-
 // Emits an if-statement with a condition that evaluates to true if |field| is
 // considered non-default (will be sent over the wire), for message types
 // without true field presence. Should only be called if
@@ -351,11 +347,11 @@
     default:
       (*variables)["val"] = PrimitiveTypeName(val->cpp_type());
   }
-  (*variables)["key_type"] =
-      "::google::protobuf::FieldDescriptor::TYPE_" +
+  (*variables)["key_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
       ToUpper(DeclaredTypeMethodName(key->type()));
-  (*variables)["val_type"] =
-      "::google::protobuf::FieldDescriptor::TYPE_" +
+  (*variables)["val_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
       ToUpper(DeclaredTypeMethodName(val->type()));
 }
 
@@ -457,17 +453,17 @@
     vars["constant_name"] = FieldConstantName(field);
 
     if (field->is_repeated()) {
-      printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
+      printer->Print(vars, "int $name$_size() const$deprecation$;\n");
     } else if (HasHasMethod(field)) {
-      printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
+      printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
     } else if (HasPrivateHasMethod(field)) {
       printer->Print(vars,
           "private:\n"
-          "inline bool has_$name$() const$deprecation$;\n"
+          "bool has_$name$() const$deprecation$;\n"
           "public:\n");
     }
 
-    printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
+    printer->Print(vars, "void clear_$name$()$deprecation$;\n");
     printer->Print(vars, "static const int $constant_name$ = $number$;\n");
 
     // Generate type-specific accessor declarations.
@@ -486,7 +482,7 @@
 
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     printer->Print(
-        "inline $camel_oneof_name$Case $oneof_name$_case() const;\n",
+        "$camel_oneof_name$Case $oneof_name$_case() const;\n",
         "camel_oneof_name",
         UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true),
         "oneof_name", descriptor_->oneof_decl(i)->name());
@@ -494,7 +490,7 @@
 }
 
 void MessageGenerator::
-GenerateFieldAccessorDefinitions(io::Printer* printer) {
+GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
   printer->Print("// $classname$\n\n", "classname", classname_);
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -504,11 +500,12 @@
 
     map<string, string> vars;
     SetCommonFieldVariables(field, &vars, options_);
+    vars["inline"] = is_inline ? "inline" : "";
 
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
       printer->Print(vars,
-        "inline int $classname$::$name$_size() const {\n"
+        "$inline$ int $classname$::$name$_size() const {\n"
         "  return $name$_.size();\n"
         "}\n");
     } else if (field->containing_oneof()) {
@@ -522,11 +519,11 @@
       vars["oneof_name"] = field->containing_oneof()->name();
       vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
       printer->Print(vars,
-        "inline bool $classname$::has_$name$() const {\n"
+        "$inline$ bool $classname$::has_$name$() const {\n"
         "  return $oneof_name$_case() == k$field_name$;\n"
         "}\n");
       printer->Print(vars,
-        "inline void $classname$::set_has_$name$() {\n"
+        "$inline$ void $classname$::set_has_$name$() {\n"
         "  _oneof_case_[$oneof_index$] = k$field_name$;\n"
         "}\n");
     } else {
@@ -539,13 +536,13 @@
         vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32),
                                              buffer);
         printer->Print(vars,
-          "inline bool $classname$::has_$name$() const {\n"
+          "$inline$ bool $classname$::has_$name$() const {\n"
           "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
           "}\n"
-          "inline void $classname$::set_has_$name$() {\n"
+          "$inline$ void $classname$::set_has_$name$() {\n"
           "  _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
           "}\n"
-          "inline void $classname$::clear_has_$name$() {\n"
+          "$inline$ void $classname$::clear_has_$name$() {\n"
           "  _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
           "}\n"
           );
@@ -555,12 +552,12 @@
           bool is_lazy = false;
           if (is_lazy) {
             printer->Print(vars,
-              "inline bool $classname$::has_$name$() const {\n"
+              "$inline$ bool $classname$::has_$name$() const {\n"
               "  return !$name$_.IsCleared();\n"
               "}\n");
           } else {
             printer->Print(vars,
-              "inline bool $classname$::has_$name$() const {\n"
+              "$inline$ bool $classname$::has_$name$() const {\n"
               "  return !_is_default_instance_ && $name$_ != NULL;\n"
               "}\n");
           }
@@ -570,7 +567,7 @@
 
     // Generate clear_$name$()
     printer->Print(vars,
-      "inline void $classname$::clear_$name$() {\n");
+      "$inline$ void $classname$::clear_$name$() {\n");
 
     printer->Indent();
 
@@ -599,7 +596,8 @@
     printer->Print("}\n");
 
     // Generate type-specific accessors.
-    field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
+    field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
+                                                                   is_inline);
 
     printer->Print("\n");
   }
@@ -612,12 +610,13 @@
     vars["cap_oneof_name"] =
         ToUpper(descriptor_->oneof_decl(i)->name());
     vars["classname"] = classname_;
+    vars["inline"] = is_inline ? "inline" : "";
     printer->Print(
       vars,
-      "inline bool $classname$::has_$oneof_name$() const {\n"
+      "$inline$ bool $classname$::has_$oneof_name$() const {\n"
       "  return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
       "}\n"
-      "inline void $classname$::clear_has_$oneof_name$() {\n"
+      "$inline$ void $classname$::clear_has_$oneof_name$() {\n"
       "  _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
       "}\n");
   }
@@ -1173,18 +1172,18 @@
 }
 
 void MessageGenerator::
-GenerateInlineMethods(io::Printer* printer) {
+GenerateInlineMethods(io::Printer* printer, bool is_inline) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // map entry message doesn't need inline methods. Since map entry message
     // cannot be a top level class, we just need to avoid calling
     // GenerateInlineMethods here.
     if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateInlineMethods(printer);
+    nested_generators_[i]->GenerateInlineMethods(printer, is_inline);
     printer->Print(kThinSeparator);
     printer->Print("\n");
   }
 
-  GenerateFieldAccessorDefinitions(printer);
+  GenerateFieldAccessorDefinitions(printer, is_inline);
 
   // Generate oneof_case() functions.
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
@@ -1194,9 +1193,10 @@
         descriptor_->oneof_decl(i)->name(), true);
     vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
     vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+    vars["inline"] = is_inline ? "inline " : "";
     printer->Print(
         vars,
-        "inline $class_name$::$camel_oneof_name$Case $class_name$::"
+        "$inline$$class_name$::$camel_oneof_name$Case $class_name$::"
         "$oneof_name$_case() const {\n"
         "  return $class_name$::$camel_oneof_name$Case("
         "_oneof_case_[$oneof_index$]);\n"
@@ -1226,7 +1226,9 @@
       for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
         const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
         printer->Print("  ");
-        if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+            (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+             EffectiveStringCType(field) != FieldOptions::STRING)) {
           printer->Print("const ");
         }
         field_generators_.get(field).GeneratePrivateMembers(printer);
@@ -1395,8 +1397,8 @@
       "      ::google::protobuf::internal::MapEntry<\n"
       "          $key$,\n"
       "          $val$,\n"
-      "          $key_type$,\n"
-      "          $val_type$,\n"
+      "          $key_wire_type$,\n"
+      "          $val_wire_type$,\n"
       "          $default_enum_value$>::CreateDefaultInstance(\n"
       "              $classname$_descriptor_));\n");
   }
@@ -2038,17 +2040,16 @@
 
   // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0.
   // The generated code uses two macros to help it clear runs of fields:
-  // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message.
+  // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the
+  // positions of two fields in the Message.
   // ZR_ zeroes a non-empty range of fields via memset.
   const char* macros =
-      "#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \\\n"
-      "  &reinterpret_cast<$classname$*>(16)->f) - \\\n"
-      "   reinterpret_cast<char*>(16))\n\n"
-      "#define ZR_(first, last) do {                              \\\n"
-      "    size_t f = OFFSET_OF_FIELD_(first);                    \\\n"
-      "    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \\\n"
-      "    ::memset(&first, 0, n);                                \\\n"
-      "  } while (0)\n\n";
+      "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
+      "  &reinterpret_cast<$classname$*>(16)->f)\n\n"
+      "#define ZR_(first, last) do {\\\n"
+      "  ::memset(&first, 0,\\\n"
+      "           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
+      "} while (0)\n\n";
   for (int i = 0; i < runs_of_fields_.size(); i++) {
     const vector<string>& run = runs_of_fields_[i];
     if (run.size() < 2) continue;
@@ -2137,7 +2138,7 @@
   }
   if (macros_are_needed) {
     printer->Outdent();
-    printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n");
+    printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n");
     printer->Indent();
   }
 
@@ -2923,8 +2924,8 @@
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
-  sort(sorted_extensions.begin(), sorted_extensions.end(),
-       ExtensionRangeSorter());
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeSorter());
 
   // Merge the fields and the extension ranges, both sorted by field number.
   int i, j;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index dfbc9af..ea96581 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -82,7 +82,7 @@
 
   // Generate definitions of inline methods (placed at the end of the header
   // file).
-  void GenerateInlineMethods(io::Printer* printer);
+  void GenerateInlineMethods(io::Printer* printer, bool is_inline);
 
   // Source file stuff.
 
@@ -116,7 +116,7 @@
  private:
   // Generate declarations and definitions of accessors for fields.
   void GenerateFieldAccessorDeclarations(io::Printer* printer);
-  void GenerateFieldAccessorDefinitions(io::Printer* printer);
+  void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
 
   // Generate the field offsets array.
   void GenerateOffsets(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index b3cd0ba..467b6bf 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -85,115 +85,83 @@
 
 void MessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline const $type$& $name$() const$deprecation$;\n"
-    "inline $type$* mutable_$name$()$deprecation$;\n"
-    "inline $type$* $release_name$()$deprecation$;\n"
-    "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
   if (SupportsArenas(descriptor_)) {
     printer->Print(variables_,
-      "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n"
-      "inline void unsafe_arena_set_allocated_$name$(\n"
+       "private:\n"
+       "void _slow_mutable_$name$()$deprecation$;\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables_,
+       "void _slow_set_allocated_$name$(\n"
+       "    ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n");
+    }
+    printer->Print(variables_,
+       "$type$* _slow_$release_name$()$deprecation$;\n"
+       "public:\n");
+  }
+  printer->Print(variables_,
+    "const $type$& $name$() const$deprecation$;\n"
+    "$type$* mutable_$name$()$deprecation$;\n"
+    "$type$* $release_name$()$deprecation$;\n"
+    "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "$type$* unsafe_arena_release_$name$()$deprecation$;\n"
+      "void unsafe_arena_set_allocated_$name$(\n"
       "    $type$* $name$)$deprecation$;\n");
   }
 }
 
-void MessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline const $type$& $classname$::$name$() const {\n"
-    "  // @@protoc_insertion_point(field_get:$full_name$)\n");
-
-  PrintHandlingOptionalStaticInitializers(
-    variables_, descriptor_->file(), printer,
-    // With static initializers.
-    "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
-    // Without.
-    "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
-
+void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
+    io::Printer* printer) const {
   if (SupportsArenas(descriptor_)) {
     printer->Print(variables_,
-      "}\n"
-      "inline $type$* $classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  if ($name$_ == NULL) {\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables_,
-      "    $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+      "void $classname$::_slow_mutable_$name$() {\n");
+      if (SupportsArenas(descriptor_->message_type())) {
+        printer->Print(variables_,
+        "  $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
       "        GetArenaNoVirtual());\n");
-    } else {
-      printer->Print(variables_,
-       "    $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
-       "        GetArenaNoVirtual());\n");
-    }
-    printer->Print(variables_, "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_;\n"
+      } else {
+        printer->Print(variables_,
+         "  $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+         "     GetArenaNoVirtual());\n");
+      }
+    printer->Print(variables_,
       "}\n"
-      "inline $type$* $classname$::$release_name$() {\n"
-      "  $clear_hasbit$\n"
-      "  if (GetArenaNoVirtual() != NULL) {\n"
-      "    if ($name$_ == NULL) {\n"
-      "      return NULL;\n"
-      "    } else {\n"
-      "      $type$* temp = new $type$;\n"
-      "      temp->MergeFrom(*$name$_);\n"
-      "      $name$_ = NULL;\n"
-      "      return temp;\n"
-      "    }\n"
+      "$type$* $classname$::_slow_$release_name$() {\n"
+      "  if ($name$_ == NULL) {\n"
+      "    return NULL;\n"
       "  } else {\n"
-      "    $type$* temp = $name$_;\n"
+      "    $type$* temp = new $type$;\n"
+      "    temp->MergeFrom(*$name$_);\n"
       "    $name$_ = NULL;\n"
       "    return temp;\n"
       "  }\n"
       "}\n"
-      "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "$type$* $classname$::unsafe_arena_release_$name$() {\n"
       "  $clear_hasbit$\n"
       "  $type$* temp = $name$_;\n"
       "  $name$_ = NULL;\n"
       "  return temp;\n"
-      "}\n"
-      "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
-      "  if (GetArenaNoVirtual() == NULL) {\n"
-      "    delete $name$_;\n"
-      "  }\n"
-      "  if ($name$ != NULL) {\n");
+      "}\n");
     if (SupportsArenas(descriptor_->message_type())) {
-      // If we're on an arena and the incoming message is not, simply Own() it
-      // rather than copy to the arena -- either way we need a heap dealloc,
-      // so we might as well defer it. Otherwise, if incoming message is on a
-      // different ownership domain (specific arena, or the heap) than we are,
-      // copy to our arena (or heap, as the case may be).
-      printer->Print(variables_,
-        "    if (GetArenaNoVirtual() != NULL && \n"
-        "        ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
-        "      GetArenaNoVirtual()->Own($name$);\n"
-        "    } else if (GetArenaNoVirtual() !=\n"
-        "               ::google::protobuf::Arena::GetArena($name$)) {\n"
-        "      $type$* new_$name$ = \n"
-        "            ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
-        "            GetArenaNoVirtual());\n"
-        "      new_$name$->CopyFrom(*$name$);\n"
-        "      $name$ = new_$name$;\n"
-        "    }\n");
-    } else {
-      printer->Print(variables_,
-        "    if (GetArenaNoVirtual() != NULL) {\n"
-        "      GetArenaNoVirtual()->Own($name$);\n"
-        "    }\n");
+        printer->Print(variables_,
+          "void $classname$::_slow_set_allocated_$name$(\n"
+          "    ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
+          "    if (message_arena != NULL && \n"
+          "        ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
+          "      message_arena->Own(*$name$);\n"
+          "    } else if (message_arena !=\n"
+          "               ::google::protobuf::Arena::GetArena(*$name$)) {\n"
+          "      $type$* new_$name$ = \n"
+          "            ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+          "            message_arena);\n"
+          "      new_$name$->CopyFrom(**$name$);\n"
+          "      *$name$ = new_$name$;\n"
+          "    }\n"
+          "}\n");
     }
-
     printer->Print(variables_,
-      "  }\n"
-      "  $name$_ = $name$;\n"
-      "  if ($name$) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n"
-      "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+      "void $classname$::unsafe_arena_set_allocated_$name$(\n"
       "    $type$* $name$) {\n"
       // If we're not on an arena, free whatever we were holding before.
       // (If we are on arena, we can just forget the earlier pointer.)
@@ -209,10 +177,80 @@
       "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
       ":$full_name$)\n"
       "}\n");
-  } else {
-    printer->Print(variables_,
+  }
+}
+
+void MessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ const $type$& $classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n");
+
+  PrintHandlingOptionalStaticInitializers(
+    variables, descriptor_->file(), printer,
+    // With static initializers.
+    "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
+    // Without.
+    "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
       "}\n"
-      "inline $type$* $classname$::mutable_$name$() {\n"
+      "$inline$ $type$* $classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  if ($name$_ == NULL) {\n"
+      "    _slow_mutable_$name$();"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_;\n"
+      "}\n"
+      "$inline$ $type$* $classname$::$release_name$() {\n"
+      "  $clear_hasbit$\n"
+      "  if (GetArenaNoVirtual() != NULL) {\n"
+      "    return _slow_$release_name$();\n"
+      "  } else {\n"
+      "    $type$* temp = $name$_;\n"
+      "    $name$_ = NULL;\n"
+      "    return temp;\n"
+      "  }\n"
+      "}\n"
+      "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+      "  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
+      "  if (message_arena == NULL) {\n"
+      "    delete $name$_;\n"
+      "  }\n"
+      "  if ($name$ != NULL) {\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      // If we're on an arena and the incoming message is not, simply Own() it
+      // rather than copy to the arena -- either way we need a heap dealloc,
+      // so we might as well defer it. Otherwise, if incoming message is on a
+      // different ownership domain (specific arena, or the heap) than we are,
+      // copy to our arena (or heap, as the case may be).
+      printer->Print(variables,
+        "    _slow_set_allocated_$name$(message_arena, &$name$);\n");
+    } else {
+      printer->Print(variables,
+        "    if (message_arena != NULL) {\n"
+        "      message_arena->Own($name$);\n"
+        "    }\n");
+    }
+    printer->Print(variables,
+      "  }\n"
+      "  $name$_ = $name$;\n"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "}\n"
+      "$inline$ $type$* $classname$::mutable_$name$() {\n"
       "  $set_hasbit$\n"
       "  if ($name$_ == NULL) {\n"
       "    $name$_ = new $type$;\n"
@@ -220,17 +258,17 @@
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $name$_;\n"
       "}\n"
-      "inline $type$* $classname$::$release_name$() {\n"
+      "$inline$ $type$* $classname$::$release_name$() {\n"
       "  $clear_hasbit$\n"
       "  $type$* temp = $name$_;\n"
       "  $name$_ = NULL;\n"
       "  return temp;\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
       "  delete $name$_;\n");
 
     if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables_,
+      printer->Print(variables,
       "  if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
       "    $type$* new_$name$ = new $type$;\n"
       "    new_$name$->CopyFrom(*$name$);\n"
@@ -238,7 +276,7 @@
       "  }\n");
     }
 
-    printer->Print(variables_,
+    printer->Print(variables,
       "  $name$_ = $name$;\n"
       "  if ($name$) {\n"
       "    $set_hasbit$\n"
@@ -328,35 +366,38 @@
 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
 
 void MessageOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "inline const $type$& $classname$::$name$() const {\n"
+    printer->Print(variables,
+      "$inline$ const $type$& $classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return has_$name$() ? *$oneof_prefix$$name$_\n"
       "                      : $type$::default_instance();\n"
       "}\n"
-      "inline $type$* $classname$::mutable_$name$() {\n"
+      "$inline$ $type$* $classname$::mutable_$name$() {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n");
     if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables_,
+      printer->Print(variables,
          "    $oneof_prefix$$name$_ = \n"
          "      ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
          "      GetArenaNoVirtual());\n");
     } else {
-      printer->Print(variables_,
+      printer->Print(variables,
          "    $oneof_prefix$$name$_ = \n"
          "      ::google::protobuf::Arena::Create< $type$ >(\n"
          "      GetArenaNoVirtual());\n");
     }
-    printer->Print(variables_,
+    printer->Print(variables,
       "  }\n"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $oneof_prefix$$name$_;\n"
       "}\n"
-      "inline $type$* $classname$::$release_name$() {\n"
+      "$inline$ $type$* $classname$::$release_name$() {\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
       "    if (GetArenaNoVirtual() != NULL) {\n"
@@ -375,7 +416,7 @@
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
       "    $type$* temp = $oneof_prefix$$name$_;\n"
@@ -385,12 +426,12 @@
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
       "  clear_$oneof_name$();\n"
       "  if ($name$) {\n");
 
     if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables_,
+      printer->Print(variables,
         // If incoming message is on the heap and we are on an arena, just Own()
         // it (see above). If it's on a different arena than we are or one of us
         // is on the heap, we make a copy to our arena/heap.
@@ -406,19 +447,19 @@
         "      $name$ = new_$name$;\n"
         "    }\n");
     } else {
-      printer->Print(variables_,
+      printer->Print(variables,
         "    if (GetArenaNoVirtual() != NULL) {\n"
         "      GetArenaNoVirtual()->Own($name$);\n"
         "    }\n");
     }
 
-    printer->Print(variables_,
+    printer->Print(variables,
       "    set_has_$name$();\n"
       "    $oneof_prefix$$name$_ = $name$;\n"
       "  }\n"
       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
       "}\n"
-      "inline void $classname$::unsafe_arena_set_allocated_$name$("
+      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
       "$type$* $name$) {\n"
       // We rely on the oneof clear method to free the earlier contents of this
       // oneof. We can directly use the pointer we're given to set the new
@@ -432,13 +473,13 @@
       "$full_name$)\n"
       "}\n");
   } else {
-    printer->Print(variables_,
-      "inline const $type$& $classname$::$name$() const {\n"
+    printer->Print(variables,
+      "$inline$ const $type$& $classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return has_$name$() ? *$oneof_prefix$$name$_\n"
       "                      : $type$::default_instance();\n"
       "}\n"
-      "inline $type$* $classname$::mutable_$name$() {\n"
+      "$inline$ $type$* $classname$::mutable_$name$() {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
@@ -447,7 +488,7 @@
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $oneof_prefix$$name$_;\n"
       "}\n"
-      "inline $type$* $classname$::$release_name$() {\n"
+      "$inline$ $type$* $classname$::$release_name$() {\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
       "    $type$* temp = $oneof_prefix$$name$_;\n"
@@ -457,18 +498,18 @@
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
       "  clear_$oneof_name$();\n"
       "  if ($name$) {\n");
     if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables_,
+      printer->Print(variables,
         "    if ($name$->GetArena() != NULL) {\n"
         "      $type$* new_$name$ = new $type$;\n"
         "      new_$name$->CopyFrom(*$name$);\n"
         "      $name$ = new_$name$;\n"
         "    }\n");
     }
-    printer->Print(variables_,
+    printer->Print(variables,
       "    set_has_$name$();\n"
       "    $oneof_prefix$$name$_ = $name$;\n"
       "  }\n"
@@ -521,38 +562,41 @@
 void RepeatedMessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline const $type$& $name$(int index) const$deprecation$;\n"
-    "inline $type$* mutable_$name$(int index)$deprecation$;\n"
-    "inline $type$* add_$name$()$deprecation$;\n");
+    "const $type$& $name$(int index) const$deprecation$;\n"
+    "$type$* mutable_$name$(int index)$deprecation$;\n"
+    "$type$* add_$name$()$deprecation$;\n");
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+    "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
     "    $name$() const$deprecation$;\n"
-    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+    "::google::protobuf::RepeatedPtrField< $type$ >*\n"
     "    mutable_$name$()$deprecation$;\n");
 }
 
 void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline const $type$& $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ const $type$& $classname$::$name$(int index) const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return $name$_.$cppget$(index);\n"
     "}\n"
-    "inline $type$* $classname$::mutable_$name$(int index) {\n"
+    "$inline$ $type$* $classname$::mutable_$name$(int index) {\n"
     "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
     "  return $name$_.Mutable(index);\n"
     "}\n"
-    "inline $type$* $classname$::add_$name$() {\n"
+    "$inline$ $type$* $classname$::add_$name$() {\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
     "  return $name$_.Add();\n"
     "}\n");
-  printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+    "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 2dff314..c1704fc 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -53,7 +53,9 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +80,9 @@
   ~MessageOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {}
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
@@ -96,7 +100,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 9a2c930..329eae3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -117,18 +117,20 @@
 void PrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline $type$ $name$() const$deprecation$;\n"
-    "inline void set_$name$($type$ value)$deprecation$;\n");
+    "$type$ $name$() const$deprecation$;\n"
+    "void set_$name$($type$ value)$deprecation$;\n");
 }
 
 void PrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "inline void $classname$::set_$name$($type$ value) {\n"
+    "$inline$ void $classname$::set_$name$($type$ value) {\n"
     "  $set_hasbit$\n"
     "  $name$_ = value;\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -204,16 +206,18 @@
 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
 
 void PrimitiveOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  if (has_$name$()) {\n"
     "    return $oneof_prefix$$name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n"
-    "inline void $classname$::set_$name$($type$ value) {\n"
+    "$inline$ void $classname$::set_$name$($type$ value) {\n"
     "  if (!has_$name$()) {\n"
     "    clear_$oneof_name$();\n"
     "    set_has_$name$();\n"
@@ -282,38 +286,40 @@
 void RepeatedPrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline $type$ $name$(int index) const$deprecation$;\n"
-    "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
-    "inline void add_$name$($type$ value)$deprecation$;\n");
+    "$type$ $name$(int index) const$deprecation$;\n"
+    "void set_$name$(int index, $type$ value)$deprecation$;\n"
+    "void add_$name$($type$ value)$deprecation$;\n");
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+    "const ::google::protobuf::RepeatedField< $type$ >&\n"
     "    $name$() const$deprecation$;\n"
-    "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+    "::google::protobuf::RepeatedField< $type$ >*\n"
     "    mutable_$name$()$deprecation$;\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$(int index) const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return $name$_.Get(index);\n"
     "}\n"
-    "inline void $classname$::set_$name$(int index, $type$ value) {\n"
+    "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
     "  $name$_.Set(index, value);\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "}\n"
-    "inline void $classname$::add_$name$($type$ value) {\n"
+    "$inline$ void $classname$::add_$name$($type$ value) {\n"
     "  $name$_.Add(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
     "}\n");
-  printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+    "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 97b5e86..fcd7d68 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -53,7 +53,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +79,8 @@
   ~PrimitiveOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
@@ -97,7 +99,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
index a8f303d..226c2aa 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -301,7 +301,7 @@
   printer->Print(vars_,
     "    default:\n"
     "      GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
-    "      return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n"
+    "      return *static_cast< ::google::protobuf::Message*>(NULL);\n"
     "  }\n"
     "}\n"
     "\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 04ed08c..1a1bcd3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -127,7 +127,11 @@
   // files that applied the ctype.  The field can still be accessed via the
   // reflection interface since the reflection interface is independent of
   // the string's underlying representation.
-  if (descriptor_->options().ctype() != FieldOptions::STRING) {
+
+  bool unknown_ctype =
+      descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+  if (unknown_ctype) {
     printer->Outdent();
     printer->Print(
       " private:\n"
@@ -136,23 +140,23 @@
   }
 
   printer->Print(variables_,
-    "inline const ::std::string& $name$() const$deprecation$;\n"
-    "inline void set_$name$(const ::std::string& value)$deprecation$;\n"
-    "inline void set_$name$(const char* value)$deprecation$;\n"
-    "inline void set_$name$(const $pointer_type$* value, size_t size)"
+    "const ::std::string& $name$() const$deprecation$;\n"
+    "void set_$name$(const ::std::string& value)$deprecation$;\n"
+    "void set_$name$(const char* value)$deprecation$;\n"
+    "void set_$name$(const $pointer_type$* value, size_t size)"
                  "$deprecation$;\n"
-    "inline ::std::string* mutable_$name$()$deprecation$;\n"
-    "inline ::std::string* $release_name$()$deprecation$;\n"
-    "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+    "::std::string* mutable_$name$()$deprecation$;\n"
+    "::std::string* $release_name$()$deprecation$;\n"
+    "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
   if (SupportsArenas(descriptor_)) {
     printer->Print(variables_,
-      "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
-      "inline void unsafe_arena_set_allocated_$name$(\n"
+      "::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
+      "void unsafe_arena_set_allocated_$name$(\n"
       "    ::std::string* $name$)$deprecation$;\n");
   }
 
 
-  if (descriptor_->options().ctype() != FieldOptions::STRING) {
+  if (unknown_ctype) {
     printer->Outdent();
     printer->Print(" public:\n");
     printer->Indent();
@@ -160,25 +164,28 @@
 }
 
 void StringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "inline const ::std::string& $classname$::$name$() const {\n"
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return $name$_.Get($default_variable$);\n"
       "}\n"
-      "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
       "  $set_hasbit$\n"
       "  $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
-      "inline void $classname$::set_$name$(const char* value) {\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
       "  $set_hasbit$\n"
       "  $name$_.Set($default_variable$, $string_piece$(value),\n"
       "              GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n"
-      "inline "
+      "$inline$ "
       "void $classname$::set_$name$(const $pointer_type$* value,\n"
       "    size_t size) {\n"
       "  $set_hasbit$\n"
@@ -186,22 +193,22 @@
       "      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
       "}\n"
-      "inline ::std::string* $classname$::mutable_$name$() {\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
       "  $set_hasbit$\n"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
       "}\n"
-      "inline ::std::string* $classname$::$release_name$() {\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
       "  $clear_hasbit$\n"
       "  return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
       "}\n"
-      "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+      "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
       "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
       "  $clear_hasbit$\n"
       "  return $name$_.UnsafeArenaRelease($default_variable$,\n"
       "      GetArenaNoVirtual());\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
       "  if ($name$ != NULL) {\n"
       "    $set_hasbit$\n"
       "  } else {\n"
@@ -211,7 +218,7 @@
       "      GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
       "}\n"
-      "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
       "    ::std::string* $name$) {\n"
       "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
       "  if ($name$ != NULL) {\n"
@@ -226,22 +233,22 @@
       "}\n");
   } else {
     // No-arena case.
-    printer->Print(variables_,
-      "inline const ::std::string& $classname$::$name$() const {\n"
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return $name$_.GetNoArena($default_variable$);\n"
       "}\n"
-      "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
       "  $set_hasbit$\n"
       "  $name$_.SetNoArena($default_variable$, value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
-      "inline void $classname$::set_$name$(const char* value) {\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
       "  $set_hasbit$\n"
       "  $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n"
-      "inline "
+      "$inline$ "
       "void $classname$::set_$name$(const $pointer_type$* value, "
       "size_t size) {\n"
       "  $set_hasbit$\n"
@@ -249,16 +256,16 @@
       "      $string_piece$(reinterpret_cast<const char*>(value), size));\n"
       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
       "}\n"
-      "inline ::std::string* $classname$::mutable_$name$() {\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
       "  $set_hasbit$\n"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $name$_.MutableNoArena($default_variable$);\n"
       "}\n"
-      "inline ::std::string* $classname$::$release_name$() {\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
       "  $clear_hasbit$\n"
       "  return $name$_.ReleaseNoArena($default_variable$);\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
       "  if ($name$ != NULL) {\n"
       "    $set_hasbit$\n"
       "  } else {\n"
@@ -422,17 +429,20 @@
 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
 
 void StringOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "inline const ::std::string& $classname$::$name$() const {\n"
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  if (has_$name$()) {\n"
       "    return $oneof_prefix$$name$_.Get($default_variable$);\n"
       "  }\n"
       "  return *$default_variable$;\n"
       "}\n"
-      "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
@@ -442,7 +452,7 @@
       "      GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
-      "inline void $classname$::set_$name$(const char* value) {\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
@@ -452,7 +462,7 @@
       "      $string_piece$(value), GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n"
-      "inline "
+      "$inline$ "
       "void $classname$::set_$name$(const $pointer_type$* value,\n"
       "                             size_t size) {\n"
       "  if (!has_$name$()) {\n"
@@ -465,7 +475,7 @@
       "      GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
       "}\n"
-      "inline ::std::string* $classname$::mutable_$name$() {\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
@@ -475,7 +485,7 @@
       "      GetArenaNoVirtual());\n"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "}\n"
-      "inline ::std::string* $classname$::$release_name$() {\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
       "    return $oneof_prefix$$name$_.Release($default_variable$,\n"
@@ -484,7 +494,7 @@
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+      "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
       "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
@@ -494,7 +504,7 @@
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
       "  if (!has_$name$()) {\n"
       "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
       "  }\n"
@@ -506,7 +516,7 @@
       "  }\n"
       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
       "}\n"
-      "inline void $classname$::unsafe_arena_set_allocated_$name$("
+      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
       "::std::string* $name$) {\n"
       "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
       "  if (!has_$name$()) {\n"
@@ -522,15 +532,15 @@
       "}\n");
   } else {
     // No-arena case.
-    printer->Print(variables_,
-      "inline const ::std::string& $classname$::$name$() const {\n"
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  if (has_$name$()) {\n"
       "    return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
       "  }\n"
       "  return *$default_variable$;\n"
       "}\n"
-      "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
@@ -540,7 +550,7 @@
       "  $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
-      "inline void $classname$::set_$name$(const char* value) {\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
@@ -550,7 +560,7 @@
       "      $string_piece$(value));\n"
       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n"
-      "inline "
+      "$inline$ "
       "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
@@ -561,7 +571,7 @@
       "      reinterpret_cast<const char*>(value), size));\n"
       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
       "}\n"
-      "inline ::std::string* $classname$::mutable_$name$() {\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
       "  if (!has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
@@ -570,7 +580,7 @@
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
       "}\n"
-      "inline ::std::string* $classname$::$release_name$() {\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
       "    return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
@@ -578,7 +588,7 @@
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
       "  if (!has_$name$()) {\n"
       "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
       "  }\n"
@@ -670,7 +680,10 @@
 void RepeatedStringFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   // See comment above about unknown ctypes.
-  if (descriptor_->options().ctype() != FieldOptions::STRING) {
+  bool unknown_ctype =
+      descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+  if (unknown_ctype) {
     printer->Outdent();
     printer->Print(
       " private:\n"
@@ -679,26 +692,26 @@
   }
 
   printer->Print(variables_,
-    "inline const ::std::string& $name$(int index) const$deprecation$;\n"
-    "inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
-    "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
-    "inline void set_$name$(int index, const char* value)$deprecation$;\n"
-    "inline "
+    "const ::std::string& $name$(int index) const$deprecation$;\n"
+    "::std::string* mutable_$name$(int index)$deprecation$;\n"
+    "void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
+    "void set_$name$(int index, const char* value)$deprecation$;\n"
+    ""
     "void set_$name$(int index, const $pointer_type$* value, size_t size)"
                  "$deprecation$;\n"
-    "inline ::std::string* add_$name$()$deprecation$;\n"
-    "inline void add_$name$(const ::std::string& value)$deprecation$;\n"
-    "inline void add_$name$(const char* value)$deprecation$;\n"
-    "inline void add_$name$(const $pointer_type$* value, size_t size)"
+    "::std::string* add_$name$()$deprecation$;\n"
+    "void add_$name$(const ::std::string& value)$deprecation$;\n"
+    "void add_$name$(const char* value)$deprecation$;\n"
+    "void add_$name$(const $pointer_type$* value, size_t size)"
                  "$deprecation$;\n");
 
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+    "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
                  "$deprecation$;\n"
-    "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+    "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
                  "$deprecation$;\n");
 
-  if (descriptor_->options().ctype() != FieldOptions::STRING) {
+  if (unknown_ctype) {
     printer->Outdent();
     printer->Print(" public:\n");
     printer->Indent();
@@ -706,54 +719,57 @@
 }
 
 void RepeatedStringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
-  printer->Print(variables_,
-    "inline const ::std::string& $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return $name$_.$cppget$(index);\n"
     "}\n"
-    "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
+    "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
     "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
     "  return $name$_.Mutable(index);\n"
     "}\n"
-    "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
+    "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "  $name$_.Mutable(index)->assign(value);\n"
     "}\n"
-    "inline void $classname$::set_$name$(int index, const char* value) {\n"
+    "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
     "  $name$_.Mutable(index)->assign(value);\n"
     "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
     "}\n"
-    "inline void "
+    "$inline$ void "
     "$classname$::set_$name$"
     "(int index, const $pointer_type$* value, size_t size) {\n"
     "  $name$_.Mutable(index)->assign(\n"
     "    reinterpret_cast<const char*>(value), size);\n"
     "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
     "}\n"
-    "inline ::std::string* $classname$::add_$name$() {\n"
+    "$inline$ ::std::string* $classname$::add_$name$() {\n"
     "  return $name$_.Add();\n"
     "}\n"
-    "inline void $classname$::add_$name$(const ::std::string& value) {\n"
+    "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
     "  $name$_.Add()->assign(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
     "}\n"
-    "inline void $classname$::add_$name$(const char* value) {\n"
+    "$inline$ void $classname$::add_$name$(const char* value) {\n"
     "  $name$_.Add()->assign(value);\n"
     "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
     "}\n"
-    "inline void "
+    "$inline$ void "
     "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
     "  $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
     "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
     "}\n");
-  printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+    "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 0a5ca44..d1f19cd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -54,7 +54,8 @@
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateStaticMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
@@ -83,7 +84,8 @@
   ~StringOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
@@ -103,7 +105,8 @@
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index e8d6f3a..1cf360c 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -83,6 +83,7 @@
   virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
   virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
       const = 0;
+  virtual void GenerateStaticInitializationCode(io::Printer* printer) const {}
 
   virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
   virtual void GenerateHashCode(io::Printer* printer) const = 0;
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 2368538..e24894b 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -690,8 +690,8 @@
   for (int i = 0; i < descriptor->field_count(); i++) {
     fields[i] = descriptor->field(i);
   }
-  sort(fields, fields + descriptor->field_count(),
-       FieldOrderingByNumber());
+  std::sort(fields, fields + descriptor->field_count(),
+            FieldOrderingByNumber());
   return fields;
 }
 
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index d957fdc..62efbef 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -297,6 +297,16 @@
 // and return it. The caller should delete the returned array.
 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor);
 
+// Does this message class have any packed fields?
+inline bool HasPackedFields(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    if (descriptor->field(i)->is_packed()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 // Check a message type and its sub-message types recursively to see if any of
 // them has a required field. Return true if a required field is found.
 bool HasRequiredFields(const Descriptor* descriptor);
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
index 21cab7d..6e29a40 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
@@ -243,9 +243,8 @@
       "}\n");
 
   printer->Print(variables_,
-      "result.$name$_.setByteString(\n"
-      "    $name$_.toByteString(),\n"
-      "    $name$_.getExtensionRegistry());\n");
+      "result.$name$_.set(\n"
+      "    $name$_);\n");
 }
 
 void ImmutableLazyMessageFieldGenerator::
@@ -425,9 +424,8 @@
 
   printer->Print(variables_,
       "result.$oneof_name$_ = new $lazy_type$();\n"
-      "(($lazy_type$) result.$oneof_name$_).setByteString(\n"
-      "    (($lazy_type$) $oneof_name$_).toByteString(),\n"
-      "    (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n");
+      "(($lazy_type$) result.$oneof_name$_).set(\n"
+      "    (($lazy_type$) $oneof_name$_));\n");
   printer->Outdent();
   printer->Print("}\n");
 }
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 2986f51..cf1ef58 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -198,25 +198,38 @@
 }
 
 void ImmutableMapFieldGenerator::
+GenerateStaticInitializationCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "$name$DefaultEntry =\n"
+      "    com.google.protobuf.MapEntry$lite$\n"
+      "    .<$type_parameters$>newDefaultInstance(\n"
+      "        $descriptor$\n"
+      "        $key_wire_type$,\n"
+      "        $key_default_value$,\n"
+      "        $value_wire_type$,\n"
+      "        $value_default_value$);\n"
+      "\n");
+}
+
+void ImmutableMapFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(
       variables_,
       "private static final com.google.protobuf.MapEntry$lite$<\n"
-      "    $type_parameters$> $name$DefaultEntry =\n"
-      "        com.google.protobuf.MapEntry$lite$\n"
-      "        .<$type_parameters$>newDefaultInstance(\n"
-      "            $descriptor$\n"
-      "            $key_wire_type$,\n"
-      "            $key_default_value$,\n"
-      "            $value_wire_type$,\n"
-      "            $value_default_value$);\n");
+      "    $type_parameters$> $name$DefaultEntry;\n");
   printer->Print(
       variables_,
       "private com.google.protobuf.MapField$lite$<\n"
-      "    $type_parameters$> $name$_ =\n"
-      "        com.google.protobuf.MapField$lite$.emptyMapField(\n"
-      "            $map_field_parameter$);\n"
-      "\n");
+      "    $type_parameters$> $name$_;\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGet$capitalized_name$() {\n"
+      "  if ($name$_ == null) {\n"
+      "    return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+      "        $map_field_parameter$);\n"
+      " }\n"
+      "  return $name$_;\n"
+      "}\n");
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -233,7 +246,7 @@
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
           "get$capitalized_name$Value() {\n"
-          "  return $name$_.getMap();\n"
+          "  return internalGet$capitalized_name$().getMap();\n"
           "}\n");
     }
     WriteFieldDocComment(printer, descriptor_);
@@ -244,7 +257,8 @@
         "get$capitalized_name$() {\n"
         "  return new com.google.protobuf.Internal.MapAdapter<\n"
         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          $name$_.getMap(), $name$ValueConverter);\n"
+        "          internalGet$capitalized_name$().getMap(),\n"
+        "          $name$ValueConverter);\n"
         "}\n");
   } else {
     WriteFieldDocComment(printer, descriptor_);
@@ -252,7 +266,7 @@
         variables_,
         "$deprecation$\n"
         "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
-        "  return $name$_.getMap();\n"
+        "  return internalGet$capitalized_name$().getMap();\n"
         "}\n");
   }
 }
@@ -262,10 +276,24 @@
   printer->Print(
       variables_,
       "private com.google.protobuf.MapField$lite$<\n"
-      "    $type_parameters$> $name$_ =\n"
-      "        com.google.protobuf.MapField$lite$.newMapField(\n"
-      "            $map_field_parameter$);\n"
-      "\n");
+      "    $type_parameters$> $name$_;\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGet$capitalized_name$() {\n"
+      "  if ($name$_ == null) {\n"
+      "    return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+      "        $map_field_parameter$);\n"
+      " }\n"
+      "  return $name$_;\n"
+      "}\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGetMutable$capitalized_name$() {\n"
+      "  $on_changed$;\n"
+      "  if ($name$_ == null) {\n"
+      "    $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+      "        $map_field_parameter$);\n"
+      " }\n"
+      "  return $name$_;\n"
+      "}\n");
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
@@ -275,7 +303,8 @@
         "get$capitalized_name$() {\n"
         "  return new com.google.protobuf.Internal.MapAdapter<\n"
         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          $name$_.getMap(), $name$ValueConverter);\n"
+        "          internalGet$capitalized_name$().getMap(),\n"
+        "          $name$ValueConverter);\n"
         "}\n");
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
@@ -283,10 +312,10 @@
         "$deprecation$\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
         "getMutable$capitalized_name$() {\n"
-        "  $on_changed$\n"
         "  return new com.google.protobuf.Internal.MapAdapter<\n"
         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          $name$_.getMutableMap(), $name$ValueConverter);\n"
+        "          internalGetMutable$capitalized_name$().getMutableMap(),\n"
+        "          $name$ValueConverter);\n"
         "}\n");
     if (SupportUnknownEnumValue(descriptor_->file())) {
       WriteFieldDocComment(printer, descriptor_);
@@ -295,7 +324,7 @@
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
           "get$capitalized_name$Value() {\n"
-          "  return $name$_.getMap();\n"
+          "  return internalGet$capitalized_name$().getMap();\n"
           "}\n");
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
@@ -303,8 +332,7 @@
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
           "getMutable$capitalized_name$Value() {\n"
-          "  $on_changed$\n"
-          "  return $name$_.getMutableMap();\n"
+          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
           "}\n");
     }
   } else {
@@ -312,15 +340,14 @@
     printer->Print(
         variables_,
         "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
-        "  return $name$_.getMap();\n"
+        "  return internalGet$capitalized_name$().getMap();\n"
         "}\n");
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "public java.util.Map<$type_parameters$>\n"
         "getMutable$capitalized_name$() {\n"
-        "  $on_changed$\n"
-        "  return $name$_.getMutableMap();\n"
+        "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
         "}\n");
   }
 }
@@ -339,14 +366,15 @@
 GenerateBuilderClearCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "$name$_.clear();\n");
+      "internalGetMutable$capitalized_name$().clear();\n");
 }
 
 void ImmutableMapFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "$name$_.mergeFrom(other.$name$_);\n");
+      "internalGetMutable$capitalized_name$().mergeFrom(\n"
+      "    other.internalGet$capitalized_name$());\n");
 }
 
 void ImmutableMapFieldGenerator::
@@ -356,7 +384,7 @@
       // We do a copy of the map field to ensure that the built result is
       // immutable. Implementation of this copy() method can do copy-on-write
       // to defer this copy until further modifications are made on the field.
-      "result.$name$_ = $name$_.copy();\n");
+      "result.$name$_ = internalGet$capitalized_name$().copy();\n");
 }
 
 void ImmutableMapFieldGenerator::
@@ -402,7 +430,7 @@
   printer->Print(
       variables_,
       "for (java.util.Map.Entry<$type_parameters$> entry\n"
-      "     : $name$_.getMap().entrySet()) {\n"
+      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
       "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
       "  $name$ = $name$DefaultEntry.newBuilderForType()\n"
       "      .setKey(entry.getKey())\n"
@@ -417,7 +445,7 @@
   printer->Print(
       variables_,
       "for (java.util.Map.Entry<$type_parameters$> entry\n"
-      "     : $name$_.getMap().entrySet()) {\n"
+      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
       "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
       "  $name$ = $name$DefaultEntry.newBuilderForType()\n"
       "      .setKey(entry.getKey())\n"
@@ -432,16 +460,17 @@
 GenerateEqualsCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "result = result && $name$_.equals(other.$name$_);\n");
+      "result = result && internalGet$capitalized_name$().equals(\n"
+      "    other.internalGet$capitalized_name$());\n");
 }
 
 void ImmutableMapFieldGenerator::
 GenerateHashCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "if (!$name$_.getMap().isEmpty()) {\n"
+      "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
       "  hash = (37 * hash) + $constant_name$;\n"
-      "  hash = (53 * hash) + $name$_.hashCode();\n"
+      "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
       "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
index 80a94f4..3e6dd97 100644
--- a/src/google/protobuf/compiler/java/java_map_field.h
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -60,6 +60,7 @@
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateStaticInitializationCode(io::Printer* printer) const;
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 1171b71..e982a17 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -234,7 +234,8 @@
         "public interface $classname$OrBuilder extends \n"
         "    $extra_interfaces$\n"
         "     com.google.protobuf.GeneratedMessageLite.\n"
-        "          ExtendableMessageOrBuilder<$classname$> {\n",
+        "          ExtendableMessageOrBuilder<\n"
+        "              $classname$, $classname$.Builder> {\n",
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "classname", descriptor_->name());
     }
@@ -285,22 +286,41 @@
   // The builder_type stores the super type name of the nested Builder class.
   string builder_type;
   if (descriptor_->extension_range_count() > 0) {
-    printer->Print(variables,
-      "public $static$final class $classname$ extends\n"
-      "    com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n"
-      "      $classname$> implements\n"
-      "    $extra_interfaces$\n"
-      "    $classname$OrBuilder {\n");
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(variables,
+        "public $static$final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
+        "      $classname$> implements\n"
+        "    $extra_interfaces$\n"
+        "    $classname$OrBuilder {\n");
+    } else {
+      printer->Print(variables,
+        "public $static$final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
+        "      $classname$, $classname$.Builder> implements\n"
+        "    $extra_interfaces$\n"
+        "    $classname$OrBuilder {\n");
+    }
     builder_type = strings::Substitute(
-        "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
-        name_resolver_->GetImmutableClassName(descriptor_),
-        variables["lite"]);
+             "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+             name_resolver_->GetImmutableClassName(descriptor_),
+             variables["lite"]);
   } else {
-    printer->Print(variables,
-      "public $static$final class $classname$ extends\n"
-      "    com.google.protobuf.GeneratedMessage$lite$ implements\n"
-      "    $extra_interfaces$\n"
-      "    $classname$OrBuilder {\n");
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(variables,
+        "public $static$final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessage implements\n"
+        "    $extra_interfaces$\n"
+        "    $classname$OrBuilder {\n");
+    } else {
+      printer->Print(variables,
+              "public $static$final class $classname$ extends\n"
+              "    com.google.protobuf.GeneratedMessageLite<\n"
+              "        $classname$, $classname$.Builder> implements\n"
+              "    $extra_interfaces$\n"
+              "    $classname$OrBuilder {\n");
+    }
+
     builder_type = strings::Substitute(
         "com.google.protobuf.GeneratedMessage$0.Builder",
         variables["lite"]);
@@ -349,7 +369,7 @@
     GenerateParsingConstructor(printer);
   }
 
-  GenerateDescriptorMethods(printer);
+  GenerateDescriptorMethods(printer, false);
   GenerateParser(printer);
 
   // Nested types
@@ -481,7 +501,7 @@
   // Carefully initialize the default instance in such a way that it doesn't
   // conflict with other initialization.
   printer->Print(
-    "private static final $classname$ defaultInstance;",
+    "private static final $classname$ defaultInstance;\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
   if (HasDescriptorMethods(descriptor_)) {
     printer->Print(
@@ -494,15 +514,11 @@
     // LITE_RUNTIME only has one constructor.
     printer->Print(
       "static {\n"
-      "  try {\n"
-      "    defaultInstance = new $classname$(\n"
-      "        com.google.protobuf.Internal\n"
-      "            .EMPTY_CODED_INPUT_STREAM,\n"
-      "        com.google.protobuf.ExtensionRegistryLite\n"
-      "            .getEmptyRegistry());\n"
-      "  } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
-      "    throw new ExceptionInInitializerError(e);\n"
-      "  }\n"
+      "  defaultInstance = new $classname$(\n"
+      "      com.google.protobuf.Internal\n"
+      "          .EMPTY_CODED_INPUT_STREAM,\n"
+      "      com.google.protobuf.ExtensionRegistryLite\n"
+      "          .getEmptyRegistry());\n"
       "}\n"
       "\n",
       "classname", descriptor_->name());
@@ -511,12 +527,30 @@
       "public static $classname$ getDefaultInstance() {\n"
       "  return defaultInstance;\n"
       "}\n"
-      "\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  if (HasDescriptorMethods(descriptor_)) {
+    // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+    printer->Print(
       "public $classname$ getDefaultInstanceForType() {\n"
       "  return defaultInstance;\n"
       "}\n"
       "\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  } else {
+    // LITE_RUNTIME uses this to implement the *ForType methods at the
+    // GeneratedMessageLite level.
+    printer->Print(
+      "static {"
+      "  com.google.protobuf.GeneratedMessageLite.onLoad(\n"
+      "      $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
+      "          .PrototypeHolder<$classname$, Builder>(\n"
+      "              defaultInstance, PARSER));"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  }
 
   // Extensions must be declared after the defaultInstance is initialized
   // because the defaultInstance is used by the extension to lazily retrieve
@@ -526,6 +560,19 @@
         .Generate(printer);
   }
 
+  // Some fields also have static members that must be initialized after we
+  // have the default instance available.
+  printer->Print(
+      "static {\n");
+  printer->Indent();
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateStaticInitializationCode(printer);
+  }
+  printer->Outdent();
+  printer->Print(
+      "}\n");
+
   printer->Outdent();
   printer->Print("}\n\n");
 }
@@ -542,37 +589,55 @@
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
-  sort(sorted_extensions.begin(), sorted_extensions.end(),
-       ExtensionRangeOrdering());
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeOrdering());
 
   printer->Print(
     "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
     "                    throws java.io.IOException {\n");
   printer->Indent();
-  // writeTo(CodedOutputStream output) might be invoked without
-  // getSerializedSize() ever being called, but we need the memoized
-  // sizes in case this message has packed fields. Rather than emit checks for
-  // each packed field, just call getSerializedSize() up front for all messages.
-  // In most cases, getSerializedSize() will have already been called anyway by
-  // one of the wrapper writeTo() methods, making this call cheap.
-  printer->Print(
-    "getSerializedSize();\n");
+  if (HasPackedFields(descriptor_)) {
+    // writeTo(CodedOutputStream output) might be invoked without
+    // getSerializedSize() ever being called, but we need the memoized
+    // sizes in case this message has packed fields. Rather than emit checks for
+    // each packed field, just call getSerializedSize() up front.
+    // In most cases, getSerializedSize() will have already been called anyway
+    // by one of the wrapper writeTo() methods, making this call cheap.
+    printer->Print(
+      "getSerializedSize();\n");
+  }
 
   if (descriptor_->extension_range_count() > 0) {
     if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "com.google.protobuf.GeneratedMessage$lite$\n"
-        "  .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
-        "    newMessageSetExtensionWriter();\n",
-        "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      if (HasDescriptorMethods(descriptor_)) {
+        printer->Print(
+          "com.google.protobuf.GeneratedMessage\n"
+          "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
+          "    extensionWriter = newMessageSetExtensionWriter();\n",
+          "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      } else {
+        printer->Print(
+          "com.google.protobuf.GeneratedMessageLite\n"
+          "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
+          "    .ExtensionWriter extensionWriter =\n"
+          "      newMessageSetExtensionWriter();\n",
+          "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      }
     } else {
-      printer->Print(
-        "com.google.protobuf.GeneratedMessage$lite$\n"
-        "  .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
-        "    newExtensionWriter();\n",
-        "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      if (HasDescriptorMethods(descriptor_)) {
+        printer->Print(
+          "com.google.protobuf.GeneratedMessage\n"
+          "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
+          "    extensionWriter = newExtensionWriter();\n",
+          "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      } else {
+        printer->Print(
+          "com.google.protobuf.GeneratedMessageLite\n"
+          "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
+          "    .ExtensionWriter extensionWriter =\n"
+          "      newExtensionWriter();\n",
+          "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      }
     }
   }
 
@@ -727,13 +792,23 @@
 // ===================================================================
 
 void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
+  if (HasDescriptorMethods(descriptor_)) {
+    // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+    printer->Print(
+      "public Builder newBuilderForType() { return newBuilder(); }\n");
+  }
+
   printer->Print(
-    "public static Builder newBuilder() { return new Builder(); }\n"
-    "public Builder newBuilderForType() { return newBuilder(); }\n"
-    "public static Builder newBuilder($classname$ prototype) {\n"
-    "  return newBuilder().mergeFrom(prototype);\n"
+    "public static Builder newBuilder() {\n"
+    "  return defaultInstance.toBuilder();\n"
     "}\n"
-    "public Builder toBuilder() { return newBuilder(this); }\n"
+    "public static Builder newBuilder($classname$ prototype) {\n"
+    "  return defaultInstance.toBuilder().mergeFrom(prototype);\n"
+    "}\n"
+    "public Builder toBuilder() {\n"
+    "  return this == defaultInstance\n"
+    "      ? new Builder() : new Builder().mergeFrom(this);\n"
+    "}\n"
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
@@ -792,7 +867,7 @@
   }
   printer->Indent();
 
-  GenerateDescriptorMethods(printer);
+  GenerateDescriptorMethods(printer, true);
   GenerateCommonBuilderMethods(printer);
 
   if (HasGeneratedMethods(descriptor_)) {
@@ -876,7 +951,7 @@
 }
 
 void ImmutableMessageGenerator::
-GenerateDescriptorMethods(io::Printer* printer) {
+GenerateDescriptorMethods(io::Printer* printer, bool is_builder) {
   if (HasDescriptorMethods(descriptor_)) {
     if (!descriptor_->options().no_standard_descriptor_accessor()) {
       printer->Print(
@@ -909,9 +984,9 @@
         const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
         printer->Print(
           "case $number$:\n"
-          "  return $name$_;\n",
+          "  return internalGet$capitalized_name$();\n",
           "number", SimpleItoa(field->number()),
-          "name", info->name);
+          "capitalized_name", info->capitalized_name);
       }
       printer->Print(
           "default:\n"
@@ -922,6 +997,34 @@
       printer->Print(
           "  }\n"
           "}\n");
+      if (is_builder) {
+        printer->Print(
+          "@SuppressWarnings({\"rawtypes\"})\n"
+          "protected com.google.protobuf.MapField internalGetMutableMapField(\n"
+          "    int number) {\n"
+          "  switch (number) {\n");
+        printer->Indent();
+        printer->Indent();
+        for (int i = 0; i < map_fields.size(); ++i) {
+          const FieldDescriptor* field = map_fields[i];
+          const FieldGeneratorInfo* info =
+              context_->GetFieldGeneratorInfo(field);
+          printer->Print(
+            "case $number$:\n"
+            "  return internalGetMutable$capitalized_name$();\n",
+            "number", SimpleItoa(field->number()),
+            "capitalized_name", info->capitalized_name);
+        }
+        printer->Print(
+            "default:\n"
+            "  throw new RuntimeException(\n"
+            "      \"Invalid map field number: \" + number);\n");
+        printer->Outdent();
+        printer->Outdent();
+        printer->Print(
+            "  }\n"
+            "}\n");
+      }
     }
     printer->Print(
       "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
@@ -959,7 +1062,7 @@
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
   } else {
     // LITE runtime passes along the default instance to implement
-    // getDefaultInstanceForType() at the GneratedMessageLite level.
+    // getDefaultInstanceForType() at the GeneratedMessageLite level.
     printer->Print(
         "// Construct using $classname$.newBuilder()\n"
         "private Builder() {\n"
@@ -1062,22 +1165,17 @@
   if (HasDescriptorMethods(descriptor_)) {
     printer->Print(
         "public $classname$ buildPartial() {\n"
-            "  $classname$ result = new $classname$(this);\n",
-         "classname", name_resolver_->GetImmutableClassName(descriptor_));
+        "  $classname$ result = new $classname$(this);\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
   } else {
     // LITE_RUNTIME only provides a single message constructor.
     printer->Print(
         "public $classname$ buildPartial() {\n"
-        "  $classname$ result = null;\n"
-        "  try {\n"
-        "    result = new $classname$(\n"
-        "        com.google.protobuf.Internal\n"
-        "            .EMPTY_CODED_INPUT_STREAM,\n"
-        "        com.google.protobuf.ExtensionRegistryLite\n"
-        "            .getEmptyRegistry());\n"
-        "  } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
-        "    throw new RuntimeException(e);\n"
-        "  }\n"
+        "  $classname$ result = new $classname$(\n"
+        "      com.google.protobuf.Internal\n"
+        "          .EMPTY_CODED_INPUT_STREAM,\n"
+        "      com.google.protobuf.ExtensionRegistryLite\n"
+        "          .getEmptyRegistry());\n"
         "  result.unknownFields = this.unknownFields;\n",
         "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
@@ -1271,6 +1369,12 @@
 
 void ImmutableMessageGenerator::GenerateIsInitialized(
     io::Printer* printer, UseMemoization useMemoization) {
+  // LITE_RUNTIME avoids generating isInitialized if it's not needed.
+  if (!HasDescriptorMethods(descriptor_)
+      && !HasRequiredFields(descriptor_)) {
+    return;
+  }
+
   bool memoization = useMemoization == MEMOIZE;
   if (memoization) {
     // Memoizes whether the protocol buffer is fully initialized (has all
@@ -1558,8 +1662,7 @@
   printer->Print(
       "private $classname$(\n"
       "    com.google.protobuf.CodedInputStream input,\n"
-      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
-      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
       "classname", descriptor_->name());
   printer->Indent();
 
@@ -1695,10 +1798,11 @@
   printer->Outdent();
   printer->Print(
       "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
-      "  throw e.setUnfinishedMessage(this);\n"
+      "  throw new RuntimeException(e.setUnfinishedMessage(this));\n"
       "} catch (java.io.IOException e) {\n"
-      "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
-      "      e.getMessage()).setUnfinishedMessage(this);\n"
+      "  throw new RuntimeException(\n"
+      "      new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "          e.getMessage()).setUnfinishedMessage(this));\n"
       "} finally {\n");
   printer->Indent();
 
@@ -1747,8 +1851,19 @@
       "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
       "classname", descriptor_->name());
   if (HasGeneratedMethods(descriptor_)) {
+    // The parsing constructor throws an InvalidProtocolBufferException via a
+    // RuntimeException to aid in method pruning. We unwrap it here.
     printer->Print(
-        "  return new $classname$(input, extensionRegistry);\n",
+        "  try {\n"
+        "    return new $classname$(input, extensionRegistry);\n"
+        "  } catch (RuntimeException e) {\n"
+        "    if (e.getCause() instanceof\n"
+        "        com.google.protobuf.InvalidProtocolBufferException) {\n"
+        "      throw (com.google.protobuf.InvalidProtocolBufferException)\n"
+        "          e.getCause();\n"
+        "    }\n"
+        "    throw e;\n"
+        "  }\n",
         "classname", descriptor_->name());
   } else {
     // When parsing constructor isn't generated, use builder to parse messages.
@@ -1775,13 +1890,16 @@
       "};\n"
       "\n");
 
-  printer->Print(
-      "@java.lang.Override\n"
-      "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
-      "  return PARSER;\n"
-      "}\n"
-      "\n",
-      "classname", descriptor_->name());
+  if (HasDescriptorMethods(descriptor_)) {
+    // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+    printer->Print(
+        "@java.lang.Override\n"
+        "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
+        "  return PARSER;\n"
+        "}\n"
+        "\n",
+        "classname", descriptor_->name());
+  }
 }
 
 // ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 91eb287..016fdd5 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -117,7 +117,7 @@
 
   void GenerateBuilder(io::Printer* printer);
   void GenerateCommonBuilderMethods(io::Printer* printer);
-  void GenerateDescriptorMethods(io::Printer* printer);
+  void GenerateDescriptorMethods(io::Printer* printer, bool is_builder);
   void GenerateBuilderParsingMethods(io::Printer* printer);
   void GenerateIsInitialized(io::Printer* printer,
       UseMemoization useMemoization);
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index 538f124..a2d12a3 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -718,6 +718,7 @@
       "    $oneof_name$_ = null;\n"
       "  }\n"
       "  $set_oneof_case_message$;\n"
+      "  $on_changed$;\n"
       "  return $name$Builder_;\n"
       "}\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index e331d7a..48757c6 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -772,6 +772,9 @@
 void RepeatedImmutablePrimitiveFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   if (descriptor_->options().packed()) {
+    // We invoke getSerializedSize in writeTo for messages that have packed
+    // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+    // That makes it safe to rely on the memoized size here.
     printer->Print(variables_,
       "if (get$capitalized_name$List().size() > 0) {\n"
       "  output.writeRawVarint32($tag$);\n"
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 2e61ea8..7017736 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -171,7 +171,7 @@
       string classname = FileJavaPackage(file_->dependency(i)) + "." +
                          name_resolver_->GetDescriptorClassName(
                              file_->dependency(i));
-      dependencies.push_back(make_pair(filename, classname));
+      dependencies.push_back(std::make_pair(filename, classname));
     }
   }
 
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 1c9302a..8aa5699 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -667,7 +667,7 @@
     printer->Print(variables_,
       "String s = input.readStringRequireUtf8();\n"
       "$set_oneof_case_message$;\n"
-      "$oneof_name$_ = s;\n}\n");
+      "$oneof_name$_ = s;\n");
   } else if (!HasDescriptorMethods(descriptor_->file())) {
     // Lite runtime should attempt to reduce allocations by attempting to
     // construct the string directly from the input stream buffer. This avoids
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
index e3e4cef..85257f3 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -36,6 +36,7 @@
 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
 #include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
 #include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
 #include <google/protobuf/compiler/javanano/javanano_message_field.h>
 #include <google/protobuf/stubs/common.h>
 
@@ -97,12 +98,24 @@
   if (field->is_repeated()) {
     switch (java_type) {
       case JAVATYPE_MESSAGE:
-        return new RepeatedMessageFieldGenerator(field, params);
+        if (IsMapEntry(field->message_type())) {
+          return new MapFieldGenerator(field, params);
+        } else {
+          return new RepeatedMessageFieldGenerator(field, params);
+        }
       case JAVATYPE_ENUM:
         return new RepeatedEnumFieldGenerator(field, params);
       default:
         return new RepeatedPrimitiveFieldGenerator(field, params);
     }
+  } else if (field->containing_oneof()) {
+    switch (java_type) {
+      case JAVATYPE_MESSAGE:
+        return new MessageOneofFieldGenerator(field, params);
+      case JAVATYPE_ENUM:
+      default:
+        return new PrimitiveOneofFieldGenerator(field, params);
+    }
   } else if (params.optional_field_accessors() && field->is_optional()
       && java_type != JAVATYPE_MESSAGE) {
     // We need a has-bit for each primitive/enum field because their default
@@ -137,6 +150,59 @@
   return *field_generators_[field->index()];
 }
 
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables) {
+  (*variables)["oneof_name"] =
+      UnderscoresToCamelCase(descriptor->containing_oneof());
+  (*variables)["oneof_capitalized_name"] =
+      UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
+  (*variables)["oneof_index"] =
+      SimpleItoa(descriptor->containing_oneof()->index());
+  (*variables)["set_oneof_case"] =
+      "this." + (*variables)["oneof_name"] +
+      "Case_ = " + SimpleItoa(descriptor->number());
+  (*variables)["clear_oneof_case"] =
+      "this." + (*variables)["oneof_name"] + "Case_ = 0";
+  (*variables)["has_oneof_case"] =
+      "this." + (*variables)["oneof_name"] + "Case_ == " +
+      SimpleItoa(descriptor->number());
+}
+
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+                              const map<string, string>& variables,
+                              io::Printer* printer) {
+  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+    printer->Print(variables,
+      "if (this.has$capitalized_name$()) {\n"
+      "  if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
+      "                               (byte[]) other.$oneof_name$_)) {\n"
+      "    return false;\n"
+      "  }\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "if (this.has$capitalized_name$()) {\n"
+      "  if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
+      "    return false;\n"
+      "  }\n"
+      "}\n");
+  }
+}
+
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+                                const map<string, string>& variables,
+                                io::Printer* printer) {
+  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+    printer->Print(variables,
+      "result = 31 * result + ($has_oneof_case$\n"
+      "   ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
+  } else {
+    printer->Print(variables,
+      "result = 31 * result +\n"
+      "  ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
+  }
+}
+
 }  // namespace javanano
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
index 6170c2c..c2cf091 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -35,6 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
 
+#include <map>
 #include <string>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.h>
@@ -111,6 +112,15 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables);
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+                              const map<string, string>& variables,
+                              io::Printer* printer);
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+                                const map<string, string>& variables,
+                                io::Printer* printer);
+
 }  // namespace javanano
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 2149418..0d2ae9d 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -154,6 +154,14 @@
   return UnderscoresToCamelCaseImpl(method->name(), false);
 }
 
+string UnderscoresToCamelCase(const OneofDescriptor* oneof) {
+  return UnderscoresToCamelCaseImpl(oneof->name(), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) {
+  return UnderscoresToCamelCaseImpl(oneof->name(), true);
+}
+
 string RenameJavaKeywords(const string& input) {
   return sRenameKeywords.RenameJavaKeywordsImpl(input);
 }
@@ -560,6 +568,17 @@
   (*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
 }
 
+bool HasMapField(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+        IsMapEntry(field->message_type())) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace javanano
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
index 2931074..014c85a 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.h
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -54,7 +54,9 @@
 // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
 // "fooBarBaz" or "FooBarBaz", respectively.
 string UnderscoresToCamelCase(const FieldDescriptor* field);
+string UnderscoresToCamelCase(const OneofDescriptor* oneof);
 string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof);
 
 // Appends an "_" to the end of a field where the name is a reserved java
 // keyword.  For example int32 public = 1 will generate int public_.
@@ -181,6 +183,14 @@
 void SetBitOperationVariables(const string name,
     int bitIndex, map<string, string>* variables);
 
+inline bool IsMapEntry(const Descriptor* descriptor) {
+  // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
+  return descriptor->options().map_entry() &&
+      descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+bool HasMapField(const Descriptor* descriptor);
+
 }  // namespace javanano
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
new file mode 100644
index 0000000..83b2b0c
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
@@ -0,0 +1,186 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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 <google/protobuf/compiler/javanano/javanano_map_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+string TypeName(const Params& params, const FieldDescriptor* field,
+                bool boxed) {
+  JavaType java_type = GetJavaType(field);
+  switch (java_type) {
+    case JAVATYPE_MESSAGE:
+      return ClassName(params, field->message_type());
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_FLOAT:
+    case JAVATYPE_DOUBLE:
+    case JAVATYPE_BOOLEAN:
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+    case JAVATYPE_ENUM:
+      if (boxed) {
+        return BoxedPrimitiveTypeName(java_type);
+      } else {
+        return PrimitiveTypeName(java_type);
+      }
+    // No default because we want the compiler to complain if any new JavaTypes
+    // are added..
+  }
+
+  GOOGLE_LOG(FATAL) << "should not reach here.";
+  return "";
+}
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("value");
+}
+
+void SetMapVariables(const Params& params,
+    const FieldDescriptor* descriptor, map<string, string>* variables) {
+  const FieldDescriptor* key = KeyField(descriptor);
+  const FieldDescriptor* value = ValueField(descriptor);
+  (*variables)["name"] =
+    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["key_type"] = TypeName(params, key, false);
+  (*variables)["boxed_key_type"] = TypeName(params,key, true);
+  (*variables)["key_desc_type"] =
+      "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type()));
+  (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key));
+  (*variables)["value_type"] = TypeName(params, value, false);
+  (*variables)["boxed_value_type"] = TypeName(params, value, true);
+  (*variables)["value_desc_type"] =
+      "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type()));
+  (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value));
+  (*variables)["type_parameters"] =
+      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+  (*variables)["value_default"] =
+      value->type() == FieldDescriptor::TYPE_MESSAGE
+          ? "new " + (*variables)["value_type"] + "()"
+          : "null";
+}
+}  // namespace
+
+// ===================================================================
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Params& params)
+    : FieldGenerator(params), descriptor_(descriptor) {
+  SetMapVariables(params, descriptor, &variables_);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public java.util.Map<$type_parameters$> $name$;\n");
+}
+
+void MapFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = null;\n");
+}
+
+void MapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n"
+    "  input, this.$name$, mapFactory,\n"
+    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+    "  com.google.protobuf.nano.InternalNano.$value_desc_type$,\n"
+    "  $value_default$,\n"
+    "  $key_tag$, $value_tag$);\n"
+    "\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  com.google.protobuf.nano.InternalNano.serializeMapField(\n"
+    "    output, this.$name$, $number$,\n"
+    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+    "}\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n"
+    "    this.$name$, $number$,\n"
+    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+    "}\n");
+}
+
+void MapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+    "  this.$name$, other.$name$)) {\n"
+    "  return false;\n"
+    "}\n");
+}
+
+void MapFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result +\n"
+    "    com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h
new file mode 100644
index 0000000..c01bde3
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+  explicit MapFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~MapFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index 7c52ca3..707f6b8 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -90,6 +90,7 @@
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // TODO(kenton):  Reuse MessageGenerator objects?
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
     MessageGenerator(descriptor_->nested_type(i), params_)
       .GenerateStaticVariables(printer);
   }
@@ -100,6 +101,7 @@
   // Generate static member initializers for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    // TODO(kenton):  Reuse MessageGenerator objects?
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
     MessageGenerator(descriptor_->nested_type(i), params_)
       .GenerateStaticVariableInitializers(printer);
   }
@@ -159,9 +161,44 @@
   }
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
     MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
   }
 
+  // oneof
+  map<string, string> vars;
+  vars["message_name"] = descriptor_->name();
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+    vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
+    vars["oneof_capitalized_name"] =
+        UnderscoresToCapitalizedCamelCase(oneof_desc);
+    vars["oneof_index"] = SimpleItoa(oneof_desc->index());
+    // Oneof Constants
+    for (int j = 0; j < oneof_desc->field_count(); j++) {
+      const FieldDescriptor* field = oneof_desc->field(j);
+      vars["number"] = SimpleItoa(field->number());
+      vars["cap_field_name"] = ToUpper(field->name());
+      printer->Print(vars,
+        "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
+    }
+    // oneofCase_ and oneof_
+    printer->Print(vars,
+      "private int $oneof_name$Case_ = 0;\n"
+      "private java.lang.Object $oneof_name$_;\n");
+    printer->Print(vars,
+      "public int get$oneof_capitalized_name$Case() {\n"
+      "  return this.$oneof_name$Case_;\n"
+      "}\n");
+    // Oneof clear
+    printer->Print(vars,
+      "public $message_name$ clear$oneof_capitalized_name$() {\n"
+      "  this.$oneof_name$Case_ = 0;\n"
+      "  this.$oneof_name$_ = null;\n"
+      "  return this;\n"
+      "}\n");
+  }
+
   // Lazy initialization of otherwise static final fields can help prevent the
   // class initializer from being generated. We want to prevent it because it
   // stops ProGuard from inlining any methods in this class into call sites and
@@ -342,6 +379,11 @@
     "classname", descriptor_->name());
 
   printer->Indent();
+  if (HasMapField(descriptor_)) {
+    printer->Print(
+      "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
+      "  com.google.protobuf.nano.MapFactories.getMapFactory();\n");
+  }
 
   printer->Print(
     "while (true) {\n");
@@ -466,6 +508,14 @@
     field_generators_.get(field).GenerateClearCode(printer);
   }
 
+  // Clear oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "clear$oneof_capitalized_name$();\n",
+      "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
+          descriptor_->oneof_decl(i)));
+  }
+
   // Clear unknown fields.
   if (params_.store_unknown_fields()) {
     printer->Print("unknownFieldData = null;\n");
@@ -501,6 +551,16 @@
     "$classname$ other = ($classname$) o;\n",
     "classname", descriptor_->name());
 
+  // Checking oneof case before checking each oneof field.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+    printer->Print(
+      "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
+      "  return false;\n"
+      "}\n",
+      "oneof_name", UnderscoresToCamelCase(oneof_desc));
+  }
+
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     field_generators_.get(field).GenerateEqualsCode(printer);
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index a46081d..181c406 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -146,12 +146,87 @@
     "result = 31 * result +\n"
     "    (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
 }
+// ===================================================================
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+    : FieldGenerator(params), descriptor_(descriptor) {
+    SetMessageVariables(params, descriptor, &variables_);
+    SetCommonOneofVariables(descriptor, &variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case$;\n"
+    "}\n"
+    "public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case$) {\n"
+    "    return ($type$) this.$oneof_name$_;\n"
+    "  }\n"
+    "  return null;\n"
+    "}\n"
+    "public $message_name$ set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) { throw new java.lang.NullPointerException(); }\n"
+    "  $set_oneof_case$;\n"
+    "  this.$oneof_name$_ = value;\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  // No clear method for oneof fields.
+}
+
+void MessageOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!($has_oneof_case$)) {\n"
+    "  this.$oneof_name$_ = new $type$();\n"
+    "}\n"
+    "input.readMessage(\n"
+    "    (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+    "$set_oneof_case$;\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  output.writeMessage($number$,\n"
+    "      (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "    .computeMessageSize($number$,\n"
+    "        (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
 
 // ===================================================================
 
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+    : FieldGenerator(params), descriptor_(descriptor) {
   SetMessageVariables(params, descriptor, &variables_);
 }
 
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
index 5d35fd2..6c615f5 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -66,6 +66,28 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
 };
 
+class MessageOneofFieldGenerator : public FieldGenerator {
+ public:
+  explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                      const Params& params);
+  ~MessageOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
 class RepeatedMessageFieldGenerator : public FieldGenerator {
  public:
   explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index a3bc3a8..41bad0a 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -155,28 +155,6 @@
   return -1;
 }
 
-// Return true if the type is a that has variable length
-// for instance String's.
-bool IsVariableLenType(JavaType type) {
-  switch (type) {
-    case JAVATYPE_INT    : return false;
-    case JAVATYPE_LONG   : return false;
-    case JAVATYPE_FLOAT  : return false;
-    case JAVATYPE_DOUBLE : return false;
-    case JAVATYPE_BOOLEAN: return false;
-    case JAVATYPE_STRING : return true;
-    case JAVATYPE_BYTES  : return true;
-    case JAVATYPE_ENUM   : return false;
-    case JAVATYPE_MESSAGE: return true;
-
-    // No default because we want the compiler to complain if any new
-    // JavaTypes are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return false;
-}
-
 bool AllAscii(const string& text) {
   for (int i = 0; i < text.size(); i++) {
     if ((text[i] & 0x80) != 0) {
@@ -186,6 +164,7 @@
   return true;
 }
 
+
 void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
                            map<string, string>* variables) {
   (*variables)["name"] =
@@ -706,8 +685,79 @@
 
 // ===================================================================
 
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+    SetPrimitiveVariables(descriptor, params, &variables_);
+    SetCommonOneofVariables(descriptor, &variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(
+    io::Printer* printer, bool /*unused lazy_init*/) const {
+  printer->Print(variables_,
+    "public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case$;\n"
+    "}\n"
+    "public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case$) {\n"
+    "    return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n"
+    "public $message_name$ set$capitalized_name$($type$ value) {\n"
+    "  $set_oneof_case$;\n"
+    "  this.$oneof_name$_ = value;\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateClearCode(
+    io::Printer* printer) const {
+  // No clear method for oneof fields.
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMergingCode(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "this.$oneof_name$_ = input.read$capitalized_type$();\n"
+    "$set_oneof_case$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  output.write$capitalized_type$(\n"
+    "      $number$, ($boxed_type$) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "      .compute$capitalized_type$Size(\n"
+    "          $number$, ($boxed_type$) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
+    io::Printer* printer) const {
+  GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
+    io::Printer* printer) const {
+  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
   : FieldGenerator(params), descriptor_(descriptor) {
   SetPrimitiveVariables(descriptor, params, &variables_);
 }
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
index c04a19b..ca7116f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -47,7 +47,7 @@
 class PrimitiveFieldGenerator : public FieldGenerator {
  public:
   explicit PrimitiveFieldGenerator(
-      const FieldDescriptor* descriptor, const Params &params);
+      const FieldDescriptor* descriptor, const Params& params);
   ~PrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
@@ -94,9 +94,32 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
 };
 
+class PrimitiveOneofFieldGenerator : public FieldGenerator {
+ public:
+  explicit PrimitiveOneofFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~PrimitiveOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
 class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Params& params);
   ~RepeatedPrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index e7d5117..9826143 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -133,10 +133,10 @@
         *error = "Saw message type MockCodeGenerator_Error.";
         return false;
       } else if (command == "Exit") {
-        cerr << "Saw message type MockCodeGenerator_Exit." << endl;
+        std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl;
         exit(123);
       } else if (command == "Abort") {
-        cerr << "Saw message type MockCodeGenerator_Abort." << endl;
+        std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl;
         abort();
       } else if (command == "HasSourceCodeInfo") {
         FileDescriptorProto file_descriptor_proto;
@@ -144,8 +144,8 @@
         bool has_source_code_info =
             file_descriptor_proto.has_source_code_info() &&
             file_descriptor_proto.source_code_info().location_size() > 0;
-        cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
-             << has_source_code_info << "." << endl;
+        std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+                  << has_source_code_info << "." << std::endl;
         abort();
       } else {
         GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index fe697ac..c50cdf5 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -277,27 +277,39 @@
   }
 }
 
-bool Parser::TryConsumeEndOfDeclaration(const char* text,
-                                        const LocationRecorder* location) {
+bool Parser::TryConsumeEndOfDeclaration(
+    const char* text, const LocationRecorder* location) {
   if (LookingAt(text)) {
     string leading, trailing;
-    input_->NextWithComments(&trailing, NULL, &leading);
+    vector<string> detached;
+    input_->NextWithComments(&trailing, &detached, &leading);
 
     // Save the leading comments for next time, and recall the leading comments
     // from last time.
     leading.swap(upcoming_doc_comments_);
 
     if (location != NULL) {
-      location->AttachComments(&leading, &trailing);
+      upcoming_detached_comments_.swap(detached);
+      location->AttachComments(&leading, &trailing, &detached);
+    } else if (strcmp(text, "}") == 0) {
+      // If the current location is null and we are finishing the current scope,
+      // drop pending upcoming detached comments.
+      upcoming_detached_comments_.swap(detached);
+    } else {
+      // Otherwise, append the new detached comments to the existing upcoming
+      // detached comments.
+      upcoming_detached_comments_.insert(upcoming_detached_comments_.end(),
+                                         detached.begin(), detached.end());
     }
+
     return true;
   } else {
     return false;
   }
 }
 
-bool Parser::ConsumeEndOfDeclaration(const char* text,
-                                     const LocationRecorder* location) {
+bool Parser::ConsumeEndOfDeclaration(
+    const char* text, const LocationRecorder* location) {
   if (TryConsumeEndOfDeclaration(text, location)) {
     return true;
   } else {
@@ -390,7 +402,8 @@
 }
 
 void Parser::LocationRecorder::AttachComments(
-    string* leading, string* trailing) const {
+    string* leading, string* trailing,
+    vector<string>* detached_comments) const {
   GOOGLE_CHECK(!location_->has_leading_comments());
   GOOGLE_CHECK(!location_->has_trailing_comments());
 
@@ -400,6 +413,11 @@
   if (!trailing->empty()) {
     location_->mutable_trailing_comments()->swap(*trailing);
   }
+  for (int i = 0; i < detached_comments->size(); ++i) {
+    location_->add_leading_detached_comments()->swap(
+        (*detached_comments)[i]);
+  }
+  detached_comments->clear();
 }
 
 // -------------------------------------------------------------------
@@ -451,16 +469,18 @@
   SourceCodeInfo source_code_info;
   source_code_info_ = &source_code_info;
 
+  vector<string> top_doc_comments;
   if (LookingAtType(io::Tokenizer::TYPE_START)) {
     // Advance to first token.
-    input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
+    input_->NextWithComments(NULL, &upcoming_detached_comments_,
+                             &upcoming_doc_comments_);
   }
 
   {
     LocationRecorder root_location(this);
 
     if (require_syntax_identifier_ || LookingAt("syntax")) {
-      if (!ParseSyntaxIdentifier()) {
+      if (!ParseSyntaxIdentifier(root_location)) {
         // Don't attempt to parse the file if we didn't recognize the syntax
         // identifier.
         return false;
@@ -469,9 +489,9 @@
       if (file != NULL) file->set_syntax(syntax_identifier_);
     } else if (!stop_after_syntax_identifier_) {
       GOOGLE_LOG(WARNING) << "No syntax specified for the proto file. "
-                          << "Please use 'syntax = \"proto2\";' or "
-                          << "'syntax = \"proto3\";' to specify a syntax "
-                          << "version. (Defaulted to proto2 syntax.)";
+                   << "Please use 'syntax = \"proto2\";' or "
+                   << "'syntax = \"proto3\";' to specify a syntax "
+                   << "version. (Defaulted to proto2 syntax.)";
       syntax_identifier_ = "proto2";
     }
 
@@ -486,7 +506,8 @@
 
         if (LookingAt("}")) {
           AddError("Unmatched \"}\".");
-          input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
+          input_->NextWithComments(NULL, &upcoming_detached_comments_,
+                                   &upcoming_doc_comments_);
         }
       }
     }
@@ -498,7 +519,9 @@
   return !had_errors_;
 }
 
-bool Parser::ParseSyntaxIdentifier() {
+bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
+  LocationRecorder syntax_location(parent,
+                                   FileDescriptorProto::kSyntaxFieldNumber);
   DO(Consume(
       "syntax",
       "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
@@ -506,7 +529,7 @@
   io::Tokenizer::Token syntax_token = input_->current();
   string syntax;
   DO(ConsumeString(&syntax, "Expected syntax identifier."));
-  DO(ConsumeEndOfDeclaration(";", NULL));
+  DO(ConsumeEndOfDeclaration(";", &syntax_location));
 
   syntax_identifier_ = syntax;
 
@@ -1271,7 +1294,6 @@
     DO(ConsumeEndOfDeclaration(";", &location));
   }
 
-
   return true;
 }
 
@@ -1636,8 +1658,14 @@
   // Parse input type.
   DO(Consume("("));
   {
-    if (TryConsume("stream")) {
+    if (LookingAt("stream")) {
+      LocationRecorder location(
+          method_location, MethodDescriptorProto::kClientStreamingFieldNumber);
+      location.RecordLegacyLocation(
+          method, DescriptorPool::ErrorCollector::OTHER);
       method->set_client_streaming(true);
+      DO(Consume("stream"));
+
     }
     LocationRecorder location(method_location,
                               MethodDescriptorProto::kInputTypeFieldNumber);
@@ -1651,8 +1679,14 @@
   DO(Consume("returns"));
   DO(Consume("("));
   {
-    if (TryConsume("stream")) {
+    if (LookingAt("stream")) {
+      LocationRecorder location(
+          method_location, MethodDescriptorProto::kServerStreamingFieldNumber);
+      location.RecordLegacyLocation(
+          method, DescriptorPool::ErrorCollector::OTHER);
+      DO(Consume("stream"));
       method->set_server_streaming(true);
+
     }
     LocationRecorder location(method_location,
                               MethodDescriptorProto::kOutputTypeFieldNumber);
@@ -1664,10 +1698,9 @@
 
   if (LookingAt("{")) {
     // Options!
-    DO(ParseOptions(method_location,
-                    containing_file,
-                    MethodDescriptorProto::kOptionsFieldNumber,
-                    method->mutable_options()));
+    DO(ParseMethodOptions(method_location, containing_file,
+                          MethodDescriptorProto::kOptionsFieldNumber,
+                          method->mutable_options()));
   } else {
     DO(ConsumeEndOfDeclaration(";", &method_location));
   }
@@ -1676,10 +1709,10 @@
 }
 
 
-bool Parser::ParseOptions(const LocationRecorder& parent_location,
-                          const FileDescriptorProto* containing_file,
-                          const int optionsFieldNumber,
-                          Message* mutable_options) {
+bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
+                                const FileDescriptorProto* containing_file,
+                                const int optionsFieldNumber,
+                                Message* mutable_options) {
   // Options!
   ConsumeEndOfDeclaration("{", &parent_location);
   while (!TryConsumeEndOfDeclaration("}", NULL)) {
@@ -1693,8 +1726,8 @@
     } else {
       LocationRecorder location(parent_location,
                                 optionsFieldNumber);
-      if (!ParseOption(mutable_options, location, containing_file,
-                       OPTION_STATEMENT)) {
+      if (!ParseOption(mutable_options, location,
+                       containing_file, OPTION_STATEMENT)) {
         // This statement failed to parse.  Skip it, but keep looping to
         // parse other statements.
         SkipStatement();
@@ -1847,7 +1880,7 @@
     DescriptorPool::ErrorCollector::ErrorLocation location,
     int* line, int* column) const {
   const pair<int, int>* result =
-    FindOrNull(location_map_, make_pair(descriptor, location));
+      FindOrNull(location_map_, std::make_pair(descriptor, location));
   if (result == NULL) {
     *line   = -1;
     *column = 0;
@@ -1863,7 +1896,8 @@
     const Message* descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location,
     int line, int column) {
-  location_map_[make_pair(descriptor, location)] = make_pair(line, column);
+  location_map_[std::make_pair(descriptor, location)] =
+      std::make_pair(line, column);
 }
 
 void SourceLocationTable::Clear() {
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index a15cc70..7cb1678 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -185,10 +185,13 @@
   //   have been passed around by const reference, for no particularly good
   //   reason.  We should probably go through and change them all to mutable
   //   pointer to make this more intuitive.
-  bool TryConsumeEndOfDeclaration(const char* text,
-                                  const LocationRecorder* location);
-  bool ConsumeEndOfDeclaration(const char* text,
-                               const LocationRecorder* location);
+  bool TryConsumeEndOfDeclaration(
+      const char* text, const LocationRecorder* location);
+  bool TryConsumeEndOfDeclarationFinishScope(
+      const char* text, const LocationRecorder* location);
+
+  bool ConsumeEndOfDeclaration(
+      const char* text, const LocationRecorder* location);
 
   // -----------------------------------------------------------------
   // Error logging helpers
@@ -253,9 +256,13 @@
     //
     // TODO(kenton):  See comment on TryConsumeEndOfDeclaration(), above, for
     //   why this is const.
-    void AttachComments(string* leading, string* trailing) const;
+    void AttachComments(string* leading, string* trailing,
+                        vector<string>* detached_comments) const;
 
    private:
+    // Indexes of parent and current location in the parent
+    // SourceCodeInfo.location repeated field. For top-level elements,
+    // parent_index_ is -1.
     Parser* parser_;
     SourceCodeInfo::Location* location_;
 
@@ -268,7 +275,7 @@
   // Parses the "syntax = \"proto2\";" line at the top of the file.  Returns
   // false if it failed to parse or if the syntax identifier was not
   // recognized.
-  bool ParseSyntaxIdentifier();
+  bool ParseSyntaxIdentifier(const LocationRecorder& parent);
 
   // These methods parse various individual bits of code.  They return
   // false if they completely fail to parse the construct.  In this case,
@@ -302,9 +309,6 @@
                    RepeatedField<int32>* weak_dependency,
                    const LocationRecorder& root_location,
                    const FileDescriptorProto* containing_file);
-  bool ParseOption(Message* options,
-                   const LocationRecorder& options_location,
-                   const FileDescriptorProto* containing_file);
 
   // These methods parse the contents of a message, enum, or service type and
   // add them to the given object.  They consume the entire block including
@@ -397,10 +401,10 @@
 
 
   // Parse options of a single method or stream.
-  bool ParseOptions(const LocationRecorder& parent_location,
-                    const FileDescriptorProto* containing_file,
-                    const int optionsFieldNumber,
-                    Message* mutable_options);
+  bool ParseMethodOptions(const LocationRecorder& parent_location,
+                          const FileDescriptorProto* containing_file,
+                          const int optionsFieldNumber,
+                          Message* mutable_options);
 
   // Parse "required", "optional", or "repeated" and fill in "label"
   // with the value. Returns true if shuch a label is consumed.
@@ -497,6 +501,13 @@
   // yet; use ConsumeEndOfDeclaration() to get the complete comments.
   string upcoming_doc_comments_;
 
+  // Detached comments are not connected to any syntax entities. Elements in
+  // this vector are paragraphs of comments separated by empty lines. The
+  // detached comments will be put into the leading_detached_comments field for
+  // the next element (See SourceCodeInfo.Location in descriptor.proto), when
+  // ConsumeEndOfDeclaration() is called.
+  vector<string> upcoming_detached_comments_;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
 };
 
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 638a83b..1684beb 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -401,13 +401,27 @@
     "  field { type:TYPE_BOOL    default_value:\"true\"      " ETC " }"
     "  field { type_name:\"Foo\" default_value:\"FOO\"       " ETC " }"
 
-    "  field { type:TYPE_INT32   default_value:\"2147483647\"           " ETC " }"
-    "  field { type:TYPE_INT32   default_value:\"-2147483648\"          " ETC " }"
-    "  field { type:TYPE_UINT32  default_value:\"4294967295\"           " ETC " }"
-    "  field { type:TYPE_INT64   default_value:\"9223372036854775807\"  " ETC " }"
-    "  field { type:TYPE_INT64   default_value:\"-9223372036854775808\" " ETC " }"
-    "  field { type:TYPE_UINT64  default_value:\"18446744073709551615\" " ETC " }"
-    "  field { type:TYPE_DOUBLE  default_value:\"43981\"                " ETC " }"
+    "  field {"
+    "    type:TYPE_INT32   default_value:\"2147483647\"           " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_INT32   default_value:\"-2147483648\"          " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_UINT32  default_value:\"4294967295\"           " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_INT64   default_value:\"9223372036854775807\"  " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_INT64   default_value:\"-9223372036854775808\" " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_UINT64  default_value:\"18446744073709551615\" " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_DOUBLE  default_value:\"43981\"                " ETC
+    "  }"
     "}");
 #undef ETC
 }
@@ -1557,7 +1571,7 @@
   }
   DescriptorProto **data =
     descriptor_proto->mutable_nested_type()->mutable_data();
-  sort(data, data + size, CompareDescriptorNames());
+  std::sort(data, data + size, CompareDescriptorNames());
 }
 
 // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
@@ -1569,7 +1583,7 @@
   }
   DescriptorProto **data =
     file_descriptor_proto->mutable_message_type()->mutable_data();
-  sort(data, data + size, CompareDescriptorNames());
+  std::sort(data, data + size, CompareDescriptorNames());
 }
 
 // Strips the message and enum field type names for comparison purpose only.
@@ -1689,25 +1703,52 @@
 // places.
 TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
   SetupParser(
+      "// Detached comment before syntax.\n"
+      "\n"
+      "// Syntax comment.\n"
+      "syntax = \"proto2\";\n"
+      "\n"
+      "// Detached comment before package.\n"
+      "\n"
+      "// Package comment.\n"
+      "package comment_test;\n"
+      "\n"
+      "// Detached comment before TestMessage1.\n"
+      "\n"
       "// Message comment.\n"
       "message TestMessage1 {\n"
+      "\n"
+      "  // Detached comment before foo.\n"
+      "\n"
       "  // Field comment.\n"
       "  optional int32 foo = 1;\n"
       "\n"
+      "  // Detached comment before NestedMessage.\n"
+      "\n"
       "  // Nested-message comment.\n"
       "  message NestedMessage {\n"
       "    optional int32 bar = 1;\n"
       "  }\n"
       "}\n"
       "\n"
+      "// Detached comment before MyEnumType.\n"
+      "\n"
       "// Enum comment.\n"
       "enum MyEnumType {\n"
+      "\n"
+      "  // Detached comment before ASDF.\n"
+      "\n"
       "  // Enum-value comment.\n"
       "  ASDF = 1;\n"
       "}\n"
       "\n"
+      "// Detached comment before MyService.\n"
+      "\n"
       "// Service comment.\n"
       "service MyService {\n"
+      "\n"
+      "  // Detached comment before MyRPCCall.\n"
+      "\n"
       "  // RPC comment.\n"
       "  rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
       "}\n");
@@ -1731,22 +1772,34 @@
   const string debug_string =
       descriptor->DebugStringWithOptions(debug_string_options);
 
-  // Ensure that each of the comments appears somewhere in the DebugString(),
-  // and that these comments appear in order. We don't test the exact comment
-  // placement or formatting, because we do not want to be too fragile here.
+  // Ensure that each of the comments appears somewhere in the DebugString().
+  // We don't test the exact comment placement or formatting, because we do not
+  // want to be too fragile here.
   const char* expected_comments[] = {
+    "Detached comment before syntax.",
+    "Syntax comment.",
+    "Detached comment before package.",
+    "Package comment.",
+    "Detached comment before TestMessage1.",
     "Message comment.",
+    "Detached comment before foo.",
     "Field comment",
+    "Detached comment before NestedMessage.",
     "Nested-message comment",
+    "Detached comment before MyEnumType.",
     "Enum comment",
+    "Detached comment before ASDF.",
     "Enum-value comment",
+    "Detached comment before MyService.",
     "Service comment",
+    "Detached comment before MyRPCCall.",
     "RPC comment",
   };
 
   for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
     string::size_type found_pos = debug_string.find(expected_comments[i]);
-    ASSERT_TRUE(found_pos != string::npos);
+    EXPECT_TRUE(found_pos != string::npos)
+        << "\"" << expected_comments[i] << "\" not found.";
   }
 }
 
@@ -1916,8 +1969,8 @@
         return false;
       }
 
-      spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
-                              &location));
+      spans_.insert(
+          std::make_pair(SpanKey(*descriptor_proto, field, index), &location));
     }
 
     return true;
@@ -1938,16 +1991,18 @@
   bool HasSpan(char start_marker, char end_marker,
                const Message& descriptor_proto) {
     return HasSpanWithComment(
-        start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL);
+        start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL);
   }
 
   bool HasSpanWithComment(char start_marker, char end_marker,
                           const Message& descriptor_proto,
                           const char* expected_leading_comments,
-                          const char* expected_trailing_comments) {
+                          const char* expected_trailing_comments,
+                          const char* expected_leading_detached_comments) {
     return HasSpanWithComment(
         start_marker, end_marker, descriptor_proto, NULL, -1,
-        expected_leading_comments, expected_trailing_comments);
+        expected_leading_comments, expected_trailing_comments,
+        expected_leading_detached_comments);
   }
 
   bool HasSpan(char start_marker, char end_marker,
@@ -1959,14 +2014,15 @@
                const Message& descriptor_proto, const string& field_name,
                int index) {
     return HasSpan(start_marker, end_marker, descriptor_proto,
-                   field_name, index, NULL, NULL);
+                   field_name, index, NULL, NULL, NULL);
   }
 
   bool HasSpan(char start_marker, char end_marker,
                const Message& descriptor_proto,
                const string& field_name, int index,
                const char* expected_leading_comments,
-               const char* expected_trailing_comments) {
+               const char* expected_trailing_comments,
+               const char* expected_leading_detached_comments) {
     const FieldDescriptor* field =
         descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
     if (field == NULL) {
@@ -1977,12 +2033,13 @@
 
     return HasSpanWithComment(
         start_marker, end_marker, descriptor_proto, field, index,
-        expected_leading_comments, expected_trailing_comments);
+        expected_leading_comments, expected_trailing_comments,
+        expected_leading_detached_comments);
   }
 
   bool HasSpan(const Message& descriptor_proto) {
     return HasSpanWithComment(
-        '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL);
+        '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL);
   }
 
   bool HasSpan(const Message& descriptor_proto, const string& field_name) {
@@ -1994,11 +2051,12 @@
     return HasSpan('\0', '\0', descriptor_proto, field_name, index);
   }
 
-  bool HasSpanWithComment(char start_marker, char end_marker,
-                          const Message& descriptor_proto,
-                          const FieldDescriptor* field, int index,
-                          const char* expected_leading_comments,
-                          const char* expected_trailing_comments) {
+  bool HasSpanWithComment(
+      char start_marker, char end_marker, const Message& descriptor_proto,
+      const FieldDescriptor* field, int index,
+      const char* expected_leading_comments,
+      const char* expected_trailing_comments,
+      const char* expected_leading_detached_comments) {
     pair<SpanMap::iterator, SpanMap::iterator> range =
         spans_.equal_range(SpanKey(descriptor_proto, field, index));
 
@@ -2037,6 +2095,13 @@
             EXPECT_EQ(expected_trailing_comments,
                       iter->second->trailing_comments());
           }
+          if (expected_leading_detached_comments == NULL) {
+            EXPECT_EQ(0, iter->second->leading_detached_comments_size());
+          } else {
+            EXPECT_EQ(
+                expected_leading_detached_comments,
+                Join(iter->second->leading_detached_comments(), "\n"));
+          }
 
           spans_.erase(iter);
           return true;
@@ -2087,7 +2152,7 @@
           text_without_markers_ += '$';
           ++column;
         } else {
-          markers_[*text] = make_pair(line, column);
+          markers_[*text] = std::make_pair(line, column);
           ++text;
           GOOGLE_CHECK_EQ('$', *text);
         }
@@ -2106,7 +2171,7 @@
 
 TEST_F(SourceInfoTest, BasicFileDecls) {
   EXPECT_TRUE(Parse(
-      "$a$syntax = \"proto2\";\n"
+      "$a$syntax = \"proto2\";$i$\n"
       "package $b$foo.bar$c$;\n"
       "import $d$\"baz.proto\"$e$;\n"
       "import $f$\"qux.proto\"$g$;$h$\n"
@@ -2117,6 +2182,7 @@
   EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
   EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
   EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
+  EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
 }
 
 TEST_F(SourceInfoTest, Messages) {
@@ -2547,6 +2613,9 @@
     "  rpc M(X) returns(Y) {\n"
     "    $g$option mopt = 1;$h$\n"
     "  }\n"
+    "  rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
+    "    $k$option mopt = 1;$l$\n"
+    "  }\n"
     "}\n"));
 
   EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
@@ -2606,6 +2675,26 @@
                       .uninterpreted_option(0).name(0), "name_part"));
   EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
                       .uninterpreted_option(0), "positive_int_value"));
+
+  EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1),
+                      "client_streaming"));
+  EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1),
+                      "server_streaming"));
 }
 
 TEST_F(SourceInfoTest, FieldOptions) {
@@ -2691,7 +2780,7 @@
       "  // Foo trailing\n"
       "  // line 2\n"
       "\n"
-      "  // ignored\n"
+      "  // detached\n"
       "\n"
       "  // bar leading\n"
       "  $b$optional int32 bar = 1;$c$\n"
@@ -2705,10 +2794,12 @@
 
   EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
       " Foo leading\n line 2\n",
-      " Foo trailing\n line 2\n"));
+      " Foo trailing\n line 2\n",
+      NULL));
   EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
       " bar leading\n",
-      " bar trailing\n"));
+      " bar trailing\n",
+      " detached\n"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -2721,21 +2812,23 @@
 
 TEST_F(SourceInfoTest, DocComments2) {
   EXPECT_TRUE(Parse(
-      "// ignored\n"
-      "syntax = \"proto2\";\n"
+      "// detached before message.\n"
+      "\n"
       "// Foo leading\n"
       "// line 2\n"
       "$a$message Foo {\n"
       "  /* Foo trailing\n"
       "   * line 2 */\n"
-      "  // ignored\n"
+      "  // detached\n"
       "  /* bar leading\n"
       "   */"
       "  $b$optional int32 bar = 1;$c$  // bar trailing\n"
-      "  // ignored\n"
+      "  // ignored detached\n"
       "}$d$\n"
       "// ignored\n"
       "\n"
+      "// detached before option\n"
+      "\n"
       "// option leading\n"
       "$e$option baz = 123;$f$\n"
       "// option trailing\n"
@@ -2747,13 +2840,16 @@
 
   EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
       " Foo leading\n line 2\n",
-      " Foo trailing\n line 2 "));
+      " Foo trailing\n line 2 ",
+      " detached before message.\n"));
   EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
       " bar leading\n",
-      " bar trailing\n"));
+      " bar trailing\n",
+      " detached\n"));
   EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
       " option leading\n",
-      " option trailing\n"));
+      " option trailing\n",
+      " detached before option\n"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -2784,7 +2880,8 @@
 
   EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
       " bar leading\n",
-      " bar trailing\n"));
+      " bar trailing\n",
+      NULL));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -2804,25 +2901,63 @@
       bar.options().uninterpreted_option(0), "aggregate_value"));
 }
 
+TEST_F(SourceInfoTest, DocCommentsTopLevel) {
+  EXPECT_TRUE(Parse(
+      "// detached before syntax paragraph 1\n"
+      "\n"
+      "// detached before syntax paragraph 2\n"
+      "\n"
+      "// syntax leading\n"
+      "$a$syntax = \"proto2\";$b$\n"
+      "// syntax trailing\n"
+      "\n"
+      "// syntax-package detached comments\n"
+      "\n"
+      ";\n"
+      "\n"
+      "// detached after empty before package\n"
+      "\n"
+      "// package leading\n"
+      "package $c$foo$d$;\n"
+      "// package trailing\n"
+      "\n"
+      "// ignored detach\n"
+      "\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1,
+      " syntax leading\n",
+      " syntax trailing\n",
+      " detached before syntax paragraph 1\n"
+      "\n"
+      " detached before syntax paragraph 2\n"));
+  EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1,
+      " package leading\n",
+      " package trailing\n",
+      " syntax-package detached comments\n"
+      "\n"
+      " detached after empty before package\n"));
+
+  // ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
 TEST_F(SourceInfoTest, DocCommentsOneof) {
   EXPECT_TRUE(Parse(
-      "// ignored\n"
-      "syntax = \"proto2\";\n"
       "// Foo leading\n"
       "$a$message Foo {\n"
       "  /* Foo trailing\n"
       "   */\n"
-      "  // ignored\n"
+      "  // detached before oneof\n"
       "  /* bar leading\n"
       "   * line 2 */\n"
       "  $b$oneof bar {\n"
       "  /* bar trailing\n"
       "   * line 2 */\n"
-      "  // ignored\n"
+      "  // detached before bar_int\n"
       "  /* bar_int leading\n"
       "   */\n"
       "  $c$int32 bar_int = 1;$d$  // bar_int trailing\n"
-      "  // ignored\n"
+      "  // detach comment ignored\n"
       "  }$e$\n"
       "}$f$\n"));
 
@@ -2832,13 +2967,16 @@
 
   EXPECT_TRUE(HasSpanWithComment('a', 'f', foo,
       " Foo leading\n",
-      " Foo trailing\n"));
+      " Foo trailing\n",
+      NULL));
   EXPECT_TRUE(HasSpanWithComment('b', 'e', bar,
       " bar leading\n line 2 ",
-      " bar trailing\n line 2 "));
+      " bar trailing\n line 2 ",
+      " detached before oneof\n"));
   EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int,
       " bar_int leading\n",
-      " bar_int trailing\n"));
+      " bar_int trailing\n",
+      " detached before bar_int\n"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 9011a6b..ad501ac 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -95,7 +95,7 @@
 int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
 
   if (argc > 1) {
-    cerr << argv[0] << ": Unknown option: " << argv[1] << endl;
+    std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl;
     return 1;
   }
 
@@ -106,7 +106,8 @@
 
   CodeGeneratorRequest request;
   if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
-    cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl;
+    std::cerr << argv[0] << ": protoc sent unparseable request to plugin."
+              << std::endl;
     return 1;
   }
 
@@ -123,9 +124,9 @@
   for (int i = 0; i < request.file_to_generate_size(); i++) {
     parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
     if (parsed_files.back() == NULL) {
-      cerr << argv[0] << ": protoc asked plugin to generate a file but "
-              "did not provide a descriptor for the file: "
-           << request.file_to_generate(i) << endl;
+      std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
+                              "did not provide a descriptor for the file: "
+                << request.file_to_generate(i) << std::endl;
       return 1;
     }
   }
@@ -151,7 +152,7 @@
   }
 
   if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
-    cerr << argv[0] << ": Error writing to stdout." << endl;
+    std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
     return 1;
   }
 
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 5118de1..fed1726 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -140,8 +140,8 @@
     "\01324.google.protobuf.compiler.CodeGenerat"
     "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
     "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB"
-    ",\n\034com.google.protobuf.compilerB\014PluginP"
-    "rotos", 445);
+    "7\n\034com.google.protobuf.compilerB\014PluginP"
+    "rotosZ\tplugin_go", 456);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
   CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
@@ -509,6 +509,147 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+ int CodeGeneratorRequest::file_to_generate_size() const {
+  return file_to_generate_.size();
+}
+ void CodeGeneratorRequest::clear_file_to_generate() {
+  file_to_generate_.Clear();
+}
+ const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Get(index);
+}
+ ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Mutable(index);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  file_to_generate_.Mutable(index)->assign(value);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+  file_to_generate_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+  file_to_generate_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+  return file_to_generate_.Add();
+}
+ void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+  file_to_generate_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+  file_to_generate_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+  file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+ bool CodeGeneratorRequest::has_parameter() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void CodeGeneratorRequest::set_has_parameter() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void CodeGeneratorRequest::clear_has_parameter() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void CodeGeneratorRequest::clear_parameter() {
+  parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_parameter();
+}
+ const ::std::string& CodeGeneratorRequest::parameter() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ ::std::string* CodeGeneratorRequest::mutable_parameter() {
+  set_has_parameter();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorRequest::release_parameter() {
+  clear_has_parameter();
+  return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+  if (parameter != NULL) {
+    set_has_parameter();
+  } else {
+    clear_has_parameter();
+  }
+  parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ int CodeGeneratorRequest::proto_file_size() const {
+  return proto_file_.size();
+}
+ void CodeGeneratorRequest::clear_proto_file() {
+  proto_file_.Clear();
+}
+ const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Get(index);
+}
+ ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Mutable(index);
+}
+ ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return &proto_file_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -1162,6 +1303,256 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+ bool CodeGeneratorResponse_File::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void CodeGeneratorResponse_File::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void CodeGeneratorResponse_File::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void CodeGeneratorResponse_File::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& CodeGeneratorResponse_File::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+
+// optional string insertion_point = 2;
+ bool CodeGeneratorResponse_File::has_insertion_point() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void CodeGeneratorResponse_File::set_has_insertion_point() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void CodeGeneratorResponse_File::clear_has_insertion_point() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void CodeGeneratorResponse_File::clear_insertion_point() {
+  insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_insertion_point();
+}
+ const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+  set_has_insertion_point();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+  clear_has_insertion_point();
+  return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+  if (insertion_point != NULL) {
+    set_has_insertion_point();
+  } else {
+    clear_has_insertion_point();
+  }
+  insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+
+// optional string content = 15;
+ bool CodeGeneratorResponse_File::has_content() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void CodeGeneratorResponse_File::set_has_content() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void CodeGeneratorResponse_File::clear_has_content() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void CodeGeneratorResponse_File::clear_content() {
+  content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_content();
+}
+ const ::std::string& CodeGeneratorResponse_File::content() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_content() {
+  set_has_content();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_content() {
+  clear_has_content();
+  return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+  if (content != NULL) {
+    set_has_content();
+  } else {
+    clear_has_content();
+  }
+  content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+ bool CodeGeneratorResponse::has_error() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void CodeGeneratorResponse::set_has_error() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void CodeGeneratorResponse::clear_has_error() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void CodeGeneratorResponse::clear_error() {
+  error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_error();
+}
+ const ::std::string& CodeGeneratorResponse::error() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
+  return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_error(const ::std::string& value) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ ::std::string* CodeGeneratorResponse::mutable_error() {
+  set_has_error();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
+  return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse::release_error() {
+  clear_has_error();
+  return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+  if (error != NULL) {
+    set_has_error();
+  } else {
+    clear_has_error();
+  }
+  error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ int CodeGeneratorResponse::file_size() const {
+  return file_.size();
+}
+ void CodeGeneratorResponse::clear_file() {
+  file_.Clear();
+}
+ const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Get(index);
+}
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Mutable(index);
+}
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return &file_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
 
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index ad01700..ea48b8b 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -110,43 +110,43 @@
   // accessors -------------------------------------------------------
 
   // repeated string file_to_generate = 1;
-  inline int file_to_generate_size() const;
-  inline void clear_file_to_generate();
+  int file_to_generate_size() const;
+  void clear_file_to_generate();
   static const int kFileToGenerateFieldNumber = 1;
-  inline const ::std::string& file_to_generate(int index) const;
-  inline ::std::string* mutable_file_to_generate(int index);
-  inline void set_file_to_generate(int index, const ::std::string& value);
-  inline void set_file_to_generate(int index, const char* value);
-  inline void set_file_to_generate(int index, const char* value, size_t size);
-  inline ::std::string* add_file_to_generate();
-  inline void add_file_to_generate(const ::std::string& value);
-  inline void add_file_to_generate(const char* value);
-  inline void add_file_to_generate(const char* value, size_t size);
-  inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
-  inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
+  const ::std::string& file_to_generate(int index) const;
+  ::std::string* mutable_file_to_generate(int index);
+  void set_file_to_generate(int index, const ::std::string& value);
+  void set_file_to_generate(int index, const char* value);
+  void set_file_to_generate(int index, const char* value, size_t size);
+  ::std::string* add_file_to_generate();
+  void add_file_to_generate(const ::std::string& value);
+  void add_file_to_generate(const char* value);
+  void add_file_to_generate(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
 
   // optional string parameter = 2;
-  inline bool has_parameter() const;
-  inline void clear_parameter();
+  bool has_parameter() const;
+  void clear_parameter();
   static const int kParameterFieldNumber = 2;
-  inline const ::std::string& parameter() const;
-  inline void set_parameter(const ::std::string& value);
-  inline void set_parameter(const char* value);
-  inline void set_parameter(const char* value, size_t size);
-  inline ::std::string* mutable_parameter();
-  inline ::std::string* release_parameter();
-  inline void set_allocated_parameter(::std::string* parameter);
+  const ::std::string& parameter() const;
+  void set_parameter(const ::std::string& value);
+  void set_parameter(const char* value);
+  void set_parameter(const char* value, size_t size);
+  ::std::string* mutable_parameter();
+  ::std::string* release_parameter();
+  void set_allocated_parameter(::std::string* parameter);
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  inline int proto_file_size() const;
-  inline void clear_proto_file();
+  int proto_file_size() const;
+  void clear_proto_file();
   static const int kProtoFileFieldNumber = 15;
-  inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
-  inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
-  inline ::google::protobuf::FileDescriptorProto* add_proto_file();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+  const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+  ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+  ::google::protobuf::FileDescriptorProto* add_proto_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
       proto_file() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
       mutable_proto_file();
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
@@ -234,40 +234,40 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // optional string insertion_point = 2;
-  inline bool has_insertion_point() const;
-  inline void clear_insertion_point();
+  bool has_insertion_point() const;
+  void clear_insertion_point();
   static const int kInsertionPointFieldNumber = 2;
-  inline const ::std::string& insertion_point() const;
-  inline void set_insertion_point(const ::std::string& value);
-  inline void set_insertion_point(const char* value);
-  inline void set_insertion_point(const char* value, size_t size);
-  inline ::std::string* mutable_insertion_point();
-  inline ::std::string* release_insertion_point();
-  inline void set_allocated_insertion_point(::std::string* insertion_point);
+  const ::std::string& insertion_point() const;
+  void set_insertion_point(const ::std::string& value);
+  void set_insertion_point(const char* value);
+  void set_insertion_point(const char* value, size_t size);
+  ::std::string* mutable_insertion_point();
+  ::std::string* release_insertion_point();
+  void set_allocated_insertion_point(::std::string* insertion_point);
 
   // optional string content = 15;
-  inline bool has_content() const;
-  inline void clear_content();
+  bool has_content() const;
+  void clear_content();
   static const int kContentFieldNumber = 15;
-  inline const ::std::string& content() const;
-  inline void set_content(const ::std::string& value);
-  inline void set_content(const char* value);
-  inline void set_content(const char* value, size_t size);
-  inline ::std::string* mutable_content();
-  inline ::std::string* release_content();
-  inline void set_allocated_content(::std::string* content);
+  const ::std::string& content() const;
+  void set_content(const ::std::string& value);
+  void set_content(const char* value);
+  void set_content(const char* value, size_t size);
+  ::std::string* mutable_content();
+  ::std::string* release_content();
+  void set_allocated_content(::std::string* content);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
  private:
@@ -360,27 +360,27 @@
   // accessors -------------------------------------------------------
 
   // optional string error = 1;
-  inline bool has_error() const;
-  inline void clear_error();
+  bool has_error() const;
+  void clear_error();
   static const int kErrorFieldNumber = 1;
-  inline const ::std::string& error() const;
-  inline void set_error(const ::std::string& value);
-  inline void set_error(const char* value);
-  inline void set_error(const char* value, size_t size);
-  inline ::std::string* mutable_error();
-  inline ::std::string* release_error();
-  inline void set_allocated_error(::std::string* error);
+  const ::std::string& error() const;
+  void set_error(const ::std::string& value);
+  void set_error(const char* value);
+  void set_error(const char* value, size_t size);
+  ::std::string* mutable_error();
+  ::std::string* release_error();
+  void set_allocated_error(::std::string* error);
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  inline int file_size() const;
-  inline void clear_file();
+  int file_size() const;
+  void clear_file();
   static const int kFileFieldNumber = 15;
-  inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
-  inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
-  inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+  const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+  ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+  ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
       file() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
       mutable_file();
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
@@ -405,6 +405,7 @@
 
 // ===================================================================
 
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
 // CodeGeneratorRequest
 
 // repeated string file_to_generate = 1;
@@ -794,6 +795,7 @@
   return &file_;
 }
 
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
 
@@ -801,15 +803,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#ifndef SWIG
-namespace google {
-namespace protobuf {
-
-
-}  // namespace protobuf
-}  // namespace google
-#endif  // SWIG
-
 // @@protoc_insertion_point(global_scope)
 
 #endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index e627289..acaee1f 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -49,6 +49,8 @@
 option java_package = "com.google.protobuf.compiler";
 option java_outer_classname = "PluginProtos";
 
+option go_package = "plugin_go";
+
 import "google/protobuf/descriptor.proto";
 
 // An encoded CodeGeneratorRequest is written to the plugin's stdin.
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index b30d197..7b3b5fa 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -273,6 +273,19 @@
   return "";
 }
 
+string StringifySyntax(FileDescriptor::Syntax syntax) {
+  switch (syntax) {
+    case FileDescriptor::SYNTAX_PROTO2:
+      return "proto2";
+    case FileDescriptor::SYNTAX_PROTO3:
+      return "proto3";
+    case FileDescriptor::SYNTAX_UNKNOWN:
+    default:
+      GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 "
+                    "and proto3 syntax.";
+      return "";
+  }
+}
 
 
 }  // namespace
@@ -367,10 +380,12 @@
   m["descriptor_name"] = kDescriptorKey;
   m["name"] = file_->name();
   m["package"] = file_->package();
+  m["syntax"] = StringifySyntax(file_->syntax());
   const char file_descriptor_template[] =
       "$descriptor_name$ = _descriptor.FileDescriptor(\n"
       "  name='$name$',\n"
-      "  package='$package$',\n";
+      "  package='$package$',\n"
+      "  syntax='$syntax$',\n";
   printer_->Print(m, file_descriptor_template);
   printer_->Indent();
   printer_->Print(
@@ -414,7 +429,7 @@
     for (int j = 0; j < enum_descriptor.value_count(); ++j) {
       const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
       top_level_enum_values.push_back(
-          make_pair(value_descriptor.name(), value_descriptor.number()));
+          std::make_pair(value_descriptor.name(), value_descriptor.number()));
     }
   }
 
@@ -581,14 +596,15 @@
 }
 
 
-void Generator::PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const {	  
+void Generator::PrintDescriptorKeyAndModuleName(
+    const ServiceDescriptor& descriptor) const {
   printer_->Print(
       "$descriptor_key$ = $descriptor_name$,\n",
       "descriptor_key", kDescriptorKey,
       "descriptor_name", ModuleLevelServiceDescriptorName(descriptor));
   printer_->Print(
       "__module__ = '$module_name$'\n",
-      "module_name", ModuleName(file_->name())); 
+      "module_name", ModuleName(file_->name()));
 }
 
 void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
@@ -664,10 +680,12 @@
   message_descriptor.options().SerializeToString(&options_string);
   printer_->Print(
       "options=$options_value$,\n"
-      "is_extendable=$extendable$",
+      "is_extendable=$extendable$,\n"
+      "syntax='$syntax$'",
       "options_value", OptionsValue("MessageOptions", options_string),
       "extendable", message_descriptor.extension_range_count() > 0 ?
-                      "True" : "False");
+                      "True" : "False",
+      "syntax", StringifySyntax(message_descriptor.file()->syntax()));
   printer_->Print(",\n");
 
   // Extension ranges
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index ee68ad7..2ddac60 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -127,7 +127,8 @@
   void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
   void PrintServiceClass(const ServiceDescriptor& descriptor) const;
   void PrintServiceStub(const ServiceDescriptor& descriptor) const;
-  void PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const ;
+  void PrintDescriptorKeyAndModuleName(
+      const ServiceDescriptor& descriptor) const ;
 
   void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
   string OptionsValue(const string& class_name,
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index c568790..a9b6837 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -47,7 +47,7 @@
 namespace ruby {
 
 // Forward decls.
-std::string IntToString(uint32_t value);
+std::string IntToString(uint32 value);
 std::string StripDotProto(const std::string& proto_file);
 std::string LabelForField(google::protobuf::FieldDescriptor* field);
 std::string TypeName(google::protobuf::FieldDescriptor* field);
@@ -64,7 +64,7 @@
     const google::protobuf::EnumDescriptor* en,
     google::protobuf::io::Printer* printer);
 
-std::string IntToString(uint32_t value) {
+std::string IntToString(uint32 value) {
   std::ostringstream os;
   os << value;
   return os.str();
@@ -100,15 +100,35 @@
   }
 }
 
-void GenerateMessage(const google::protobuf::Descriptor* message,
-                     google::protobuf::io::Printer* printer) {
-  printer->Print(
-    "add_message \"$name$\" do\n",
-    "name", message->full_name());
-  printer->Indent();
+void GenerateField(const google::protobuf::FieldDescriptor* field,
+                   google::protobuf::io::Printer* printer) {
 
-  for (int i = 0; i < message->field_count(); i++) {
-    const FieldDescriptor* field = message->field(i);
+  if (field->is_map()) {
+    const FieldDescriptor* key_field =
+        field->message_type()->FindFieldByNumber(1);
+    const FieldDescriptor* value_field =
+        field->message_type()->FindFieldByNumber(2);
+
+    printer->Print(
+      "map :$name$, :$key_type$, :$value_type$, $number$",
+      "name", field->name(),
+      "key_type", TypeName(key_field),
+      "value_type", TypeName(value_field),
+      "number", IntToString(field->number()));
+
+    if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      printer->Print(
+        ", \"$subtype$\"\n",
+        "subtype", value_field->message_type()->full_name());
+    } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      printer->Print(
+        ", \"$subtype$\"\n",
+        "subtype", value_field->enum_type()->full_name());
+    } else {
+      printer->Print("\n");
+    }
+  } else {
+
     printer->Print(
       "$label$ :$name$, ",
       "label", LabelForField(field),
@@ -117,6 +137,7 @@
       ":$type$, $number$",
       "type", TypeName(field),
       "number", IntToString(field->number()));
+
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       printer->Print(
         ", \"$subtype$\"\n",
@@ -129,6 +150,49 @@
       printer->Print("\n");
     }
   }
+}
+
+void GenerateOneof(const google::protobuf::OneofDescriptor* oneof,
+                   google::protobuf::io::Printer* printer) {
+  printer->Print(
+      "oneof :$name$ do\n",
+      "name", oneof->name());
+  printer->Indent();
+
+  for (int i = 0; i < oneof->field_count(); i++) {
+    const FieldDescriptor* field = oneof->field(i);
+    GenerateField(field, printer);
+  }
+
+  printer->Outdent();
+  printer->Print("end\n");
+}
+
+void GenerateMessage(const google::protobuf::Descriptor* message,
+                     google::protobuf::io::Printer* printer) {
+
+  // Don't generate MapEntry messages -- we use the Ruby extension's native
+  // support for map fields instead.
+  if (message->options().map_entry()) {
+    return;
+  }
+
+  printer->Print(
+    "add_message \"$name$\" do\n",
+    "name", message->full_name());
+  printer->Indent();
+
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    if (!field->containing_oneof()) {
+      GenerateField(field, printer);
+    }
+  }
+
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    GenerateOneof(oneof, printer);
+  }
 
   printer->Outdent();
   printer->Print("end\n");
@@ -185,6 +249,13 @@
     const std::string& prefix,
     const google::protobuf::Descriptor* message,
     google::protobuf::io::Printer* printer) {
+
+  // Don't generate MapEntry messages -- we use the Ruby extension's native
+  // support for map fields instead.
+  if (message->options().map_entry()) {
+    return;
+  }
+
   printer->Print(
     "$prefix$$name$ = ",
     "prefix", prefix,
@@ -307,7 +378,8 @@
 
   std::string filename =
       StripDotProto(file->name()) + ".rb";
-  scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(filename));
+  scoped_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
   io::Printer printer(output.get(), '$');
 
   GenerateFile(file, &printer);
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
index 48dbefd..75555c3 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.h
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -40,7 +40,8 @@
 namespace compiler {
 namespace ruby {
 
-class Generator : public google::protobuf::compiler::CodeGenerator {
+class LIBPROTOC_EXPORT Generator
+    : public google::protobuf::compiler::CodeGenerator {
   virtual bool Generate(
       const FileDescriptor* file,
       const string& parameter,
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
new file mode 100644
index 0000000..e35ca69
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -0,0 +1,119 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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 <memory>
+
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+namespace {
+
+string FindRubyTestDir() {
+  // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc.
+  string prefix = ".";
+  while (!File::Exists(prefix + "/ruby/tests")) {
+    if (!File::Exists(prefix)) {
+      GOOGLE_LOG(FATAL)
+          << "Could not find Ruby test directory. Please run tests from "
+             "somewhere within the protobuf source package.";
+    }
+    prefix += "/..";
+  }
+  return prefix + "/ruby/tests";
+}
+
+// This test is a simple golden-file test over the output of the Ruby code
+// generator. When we make changes to the Ruby extension and alter the Ruby code
+// generator to use those changes, we should (i) manually test the output of the
+// code generator with the extension, and (ii) update the golden output above.
+// Some day, we may integrate build systems between protoc and the language
+// extensions to the point where we can do this test in a more automated way.
+
+TEST(RubyGeneratorTest, GeneratorTest) {
+  string ruby_tests = FindRubyTestDir();
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  ruby::Generator ruby_generator;
+  cli.RegisterGenerator("--ruby_out", &ruby_generator, "");
+
+  // Copy generated_code.proto to the temporary test directory.
+  string test_input;
+  GOOGLE_CHECK_OK(File::GetContents(
+      ruby_tests + "/generated_code.proto",
+      &test_input,
+      true));
+  GOOGLE_CHECK_OK(File::SetContents(
+      TestTempDir() + "/generated_code.proto",
+      test_input,
+      true));
+
+  // Invoke the proto compiler (we will be inside TestTempDir() at this point).
+  string ruby_out = "--ruby_out=" + TestTempDir();
+  string proto_path = "--proto_path=" + TestTempDir();
+  const char* argv[] = {
+    "protoc",
+    ruby_out.c_str(),
+    proto_path.c_str(),
+    "generated_code.proto",
+  };
+
+  EXPECT_EQ(0, cli.Run(4, argv));
+
+  // Load the generated output and compare to the expected result.
+  string output;
+  GOOGLE_CHECK_OK(File::GetContents(
+      TestTempDir() + "/generated_code.rb",
+      &output,
+      true));
+  string expected_output;
+  GOOGLE_CHECK_OK(File::GetContents(
+      ruby_tests + "/generated_code.rb",
+      &expected_output,
+      true));
+  EXPECT_EQ(expected_output, output);
+}
+
+}  // namespace
+}  // namespace ruby
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index b8dd198..bfdacd9 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -783,7 +783,7 @@
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
     const Descriptor* parent, int number) const {
-  return FindPtrOrNull(fields_by_number_, make_pair(parent, number));
+  return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
@@ -800,7 +800,7 @@
 
 inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
     const EnumDescriptor* parent, int number) const {
-  return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
+  return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
 }
 
 inline const EnumValueDescriptor*
@@ -808,8 +808,8 @@
     const EnumDescriptor* parent, int number) const {
   // First try, with map of compiled-in values.
   {
-    const EnumValueDescriptor* desc = FindPtrOrNull(
-        enum_values_by_number_, make_pair(parent, number));
+    const EnumValueDescriptor* desc =
+        FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
     if (desc != NULL) {
       return desc;
     }
@@ -818,7 +818,7 @@
   {
     ReaderMutexLock l(&unknown_enum_values_mu_);
     const EnumValueDescriptor* desc = FindPtrOrNull(
-        unknown_enum_values_by_number_, make_pair(parent, number));
+        unknown_enum_values_by_number_, std::make_pair(parent, number));
     if (desc != NULL) {
       return desc;
     }
@@ -828,7 +828,7 @@
   {
     WriterMutexLock l(&unknown_enum_values_mu_);
     const EnumValueDescriptor* desc = FindPtrOrNull(
-        unknown_enum_values_by_number_, make_pair(parent, number));
+        unknown_enum_values_by_number_, std::make_pair(parent, number));
     if (desc != NULL) {
       return desc;
     }
@@ -850,8 +850,7 @@
     result->type_ = parent;
     result->options_ = &EnumValueOptions::default_instance();
     InsertIfNotPresent(&unknown_enum_values_by_number_,
-                       make_pair(parent, number),
-                       result);
+                       std::make_pair(parent, number), result);
     return result;
   }
 }
@@ -859,13 +858,13 @@
 
 inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
     const Descriptor* extendee, int number) {
-  return FindPtrOrNull(extensions_, make_pair(extendee, number));
+  return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
 }
 
 inline void DescriptorPool::Tables::FindAllExtensions(
     const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
   ExtensionsGroupedByDescriptorMap::const_iterator it =
-      extensions_.lower_bound(make_pair(extendee, 0));
+      extensions_.lower_bound(std::make_pair(extendee, 0));
   for (; it != extensions_.end() && it->first.first == extendee; ++it) {
     out->push_back(it->second);
   }
@@ -993,7 +992,7 @@
 const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
     const vector<int>& path, const SourceCodeInfo* info) const {
   pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
-      make_pair(this, info));
+      std::make_pair(this, info));
   locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
   return FindPtrOrNull(locations_by_path_, Join(path, ","));
 }
@@ -1929,9 +1928,9 @@
   return !all_options.empty();
 }
 
-template<typename DescType>
 class SourceLocationCommentPrinter {
  public:
+  template<typename DescType>
   SourceLocationCommentPrinter(const DescType* desc,
                                const string& prefix,
                                const DebugStringOptions& options)
@@ -1941,9 +1940,27 @@
     have_source_loc_ = options.include_comments &&
         desc->GetSourceLocation(&source_loc_);
   }
+  SourceLocationCommentPrinter(const FileDescriptor* file,
+                               const vector<int>& path,
+                               const string& prefix,
+                               const DebugStringOptions& options)
+      : options_(options), prefix_(prefix) {
+    // Perform the SourceLocation lookup only if we're including user comments,
+    // because the lookup is fairly expensive.
+    have_source_loc_ = options.include_comments &&
+        file->GetSourceLocation(path, &source_loc_);
+  }
   void AddPreComment(string* output) {
-    if (have_source_loc_ && source_loc_.leading_comments.size() > 0) {
-      *output += FormatComment(source_loc_.leading_comments);
+    if (have_source_loc_) {
+      // Detached leading comments.
+      for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) {
+        *output += FormatComment(source_loc_.leading_detached_comments[i]);
+        *output += "\n";
+      }
+      // Attached leading comments.
+      if (!source_loc_.leading_comments.empty()) {
+        *output += FormatComment(source_loc_.leading_comments);
+      }
     }
   }
   void AddPostComment(string* output) {
@@ -1967,7 +1984,6 @@
   }
 
  private:
-  const DescType* desc_;
   bool have_source_loc_;
   SourceLocation source_loc_;
   DebugStringOptions options_;
@@ -1984,10 +2000,18 @@
 string FileDescriptor::DebugStringWithOptions(
     const DebugStringOptions& debug_string_options) const {
   string contents;
-  strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
-                               SyntaxName(syntax()));
+  {
+    vector<int> path;
+    path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
+    SourceLocationCommentPrinter syntax_comment(
+        this, path, "", debug_string_options);
+    syntax_comment.AddPreComment(&contents);
+    strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
+                                 SyntaxName(syntax()));
+    syntax_comment.AddPostComment(&contents);
+  }
 
-  SourceLocationCommentPrinter<FileDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, "", debug_string_options);
   comment_printer.AddPreComment(&contents);
 
@@ -2012,7 +2036,13 @@
   }
 
   if (!package().empty()) {
+    vector<int> path;
+    path.push_back(FileDescriptorProto::kPackageFieldNumber);
+    SourceLocationCommentPrinter package_comment(
+        this, path, "", debug_string_options);
+    package_comment.AddPreComment(&contents);
     strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
+    package_comment.AddPostComment(&contents);
   }
 
   if (FormatLineOptions(0, options(), &contents)) {
@@ -2087,7 +2117,7 @@
   string prefix(depth * 2, ' ');
   ++depth;
 
-  SourceLocationCommentPrinter<Descriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, prefix, debug_string_options);
   comment_printer.AddPreComment(contents);
 
@@ -2217,7 +2247,7 @@
     label.push_back(' ');
   }
 
-  SourceLocationCommentPrinter<FieldDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, prefix, debug_string_options);
   comment_printer.AddPreComment(contents);
 
@@ -2274,7 +2304,7 @@
                                   debug_string_options) const {
   string prefix(depth * 2, ' ');
   ++depth;
-  SourceLocationCommentPrinter<OneofDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, prefix, debug_string_options);
   comment_printer.AddPreComment(contents);
   strings::SubstituteAndAppend(
@@ -2305,7 +2335,7 @@
   string prefix(depth * 2, ' ');
   ++depth;
 
-  SourceLocationCommentPrinter<EnumDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, prefix, debug_string_options);
   comment_printer.AddPreComment(contents);
 
@@ -2339,7 +2369,7 @@
                                       debug_string_options) const {
   string prefix(depth * 2, ' ');
 
-  SourceLocationCommentPrinter<EnumValueDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, prefix, debug_string_options);
   comment_printer.AddPreComment(contents);
 
@@ -2370,7 +2400,7 @@
 void ServiceDescriptor::DebugString(string *contents,
                                     const DebugStringOptions&
                                     debug_string_options) const {
-  SourceLocationCommentPrinter<ServiceDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, /* prefix */ "", debug_string_options);
   comment_printer.AddPreComment(contents);
 
@@ -2405,7 +2435,7 @@
   string prefix(depth * 2, ' ');
   ++depth;
 
-  SourceLocationCommentPrinter<MethodDescriptor>
+  SourceLocationCommentPrinter
       comment_printer(this, prefix, debug_string_options);
   comment_printer.AddPreComment(contents);
 
@@ -2445,6 +2475,9 @@
 
         out_location->leading_comments = loc->leading_comments();
         out_location->trailing_comments = loc->trailing_comments();
+        out_location->leading_detached_comments.assign(
+            loc->leading_detached_comments().begin(),
+            loc->leading_detached_comments().end());
         return true;
       }
     }
@@ -3697,7 +3730,6 @@
              "Unrecognized syntax: " + proto.syntax());
   }
 
-
   result->name_ = tables_->AllocateString(proto.name());
   if (proto.has_package()) {
     result->package_ = tables_->AllocateString(proto.package());
@@ -5110,7 +5142,7 @@
     case FieldDescriptor::TYPE_SFIXED64:
       // Legal cases
       break;
-    // Do not add a default, so that the compiler will complian when new types
+    // Do not add a default, so that the compiler will complain when new types
     // are added.
   }
 
@@ -5123,7 +5155,7 @@
   for (int i = 0; i < message->nested_type_count(); ++i) {
     const Descriptor* nested = message->nested_type(i);
     pair<map<string, const Descriptor*>::iterator, bool> result =
-        seen_types.insert(make_pair(nested->name(), nested));
+        seen_types.insert(std::make_pair(nested->name(), nested));
     if (!result.second) {
       if (result.first->second->options().map_entry() ||
           nested->options().map_entry()) {
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 52df47f..0e264f5 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -117,8 +117,10 @@
   int end_column;
 
   // Doc comments found at the source location.
+  // See the comments in SourceCodeInfo.Location (descriptor.proto) for details.
   string leading_comments;
   string trailing_comments;
+  vector<string> leading_detached_comments;
 };
 
 // Options when generating machine-parsable output from a descriptor with
@@ -312,7 +314,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -594,7 +596,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -688,7 +690,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -790,7 +792,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -874,7 +876,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -949,7 +951,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -1028,7 +1030,7 @@
 
   // Walks up the descriptor tree to generate the source location path
   // to this descriptor from the file root.
-  void GetLocationPath(vector<int>* output) const;
+  void GetLocationPath(std::vector<int>* output) const;
 
   const string* name_;
   const string* full_name_;
@@ -1173,17 +1175,15 @@
   // this file declaration (namely, the empty path).
   bool GetSourceLocation(SourceLocation* out_location) const;
 
- private:
-  // Source Location ---------------------------------------------------
-
   // Updates |*out_location| to the source location of the complete
   // extent of the declaration or declaration-part denoted by |path|.
   // Returns false and leaves |*out_location| unchanged iff location
   // information was not available.  (See SourceCodeInfo for
   // description of path encoding.)
-  bool GetSourceLocation(const vector<int>& path,
+  bool GetSourceLocation(const std::vector<int>& path,
                          SourceLocation* out_location) const;
 
+ private:
   typedef FileOptions OptionsType;
 
   const string* name_;
@@ -1326,7 +1326,7 @@
   // found: extensions defined in the fallback database might not be found
   // depending on the database implementation.
   void FindAllExtensions(const Descriptor* extendee,
-                         vector<const FieldDescriptor*>* out) const;
+                         std::vector<const FieldDescriptor*>* out) const;
 
   // Building descriptors --------------------------------------------
 
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 97121fa..9556206 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -289,7 +289,7 @@
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_),
       -1);
   FileOptions_descriptor_ = file->message_type(9);
-  static const int FileOptions_offsets_[13] = {
+  static const int FileOptions_offsets_[14] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
@@ -302,6 +302,7 @@
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
   };
   FileOptions_reflection_ =
@@ -474,11 +475,12 @@
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_),
       -1);
   SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
-  static const int SourceCodeInfo_Location_offsets_[4] = {
+  static const int SourceCodeInfo_Location_offsets_[5] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_),
   };
   SourceCodeInfo_Location_reflection_ =
     ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -661,7 +663,7 @@
     "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p"
     "rotobuf.MethodOptions\022\037\n\020client_streamin"
     "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010"
-    ":\005false\"\314\004\n\013FileOptions\022\024\n\014java_package\030"
+    ":\005false\"\347\004\n\013FileOptions\022\024\n\014java_package\030"
     "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j"
     "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_"
     "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n"
@@ -672,49 +674,51 @@
     "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal"
     "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031"
     "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a"
-    "renas\030\037 \001(\010:\005false\022C\n\024uninterpreted_opti"
+    "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030"
+    "$ \001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g"
+    "oogle.protobuf.UninterpretedOption\":\n\014Op"
+    "timizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014"
+    "LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOpt"
+    "ions\022&\n\027message_set_wire_format\030\001 \001(\010:\005f"
+    "alse\022.\n\037no_standard_descriptor_accessor\030"
+    "\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
+    "\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpreted_opti"
     "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
-    "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
-    "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346"
-    "\001\n\016MessageOptions\022&\n\027message_set_wire_fo"
-    "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
-    "tor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030"
-    "\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024unint"
-    "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
-    ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014Fiel"
-    "dOptions\022:\n\005ctype\030\001 \001(\0162#.google.protobu"
-    "f.FieldOptions.CType:\006STRING\022\016\n\006packed\030\002"
-    " \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030"
-    "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni"
-    "nterpreted_option\030\347\007 \003(\0132$.google.protob"
-    "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN"
-    "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200"
-    "\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022"
-    "\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uninterpre"
-    "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
-    "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueO"
-    "ptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uni"
-    "nterpreted_option\030\347\007 \003(\0132$.google.protob"
-    "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016Ser"
-    "viceOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C"
-    "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
-    "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z"
-    "\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:\005fal"
-    "se\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog"
-    "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200"
-    "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013"
-    "2-.google.protobuf.UninterpretedOption.N"
-    "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos"
-    "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va"
-    "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin"
-    "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323"
-    "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte"
-    "nsion\030\002 \002(\010\"\261\001\n\016SourceCodeInfo\022:\n\010locati"
-    "on\030\001 \003(\0132(.google.protobuf.SourceCodeInf"
-    "o.Location\032c\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001"
-    "\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003"
-    " \001(\t\022\031\n\021trailing_comments\030\004 \001(\tB)\n\023com.g"
-    "oogle.protobufB\020DescriptorProtosH\001", 4554);
+    "dOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005c"
+    "type\030\001 \001(\0162#.google.protobuf.FieldOption"
+    "s.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030"
+    "\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
+    "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op"
+    "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+    "tedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001"
+    "\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOp"
+    "tions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated"
+    "\030\003 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007"
+    " \003(\0132$.google.protobuf.UninterpretedOpti"
+    "on*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndep"
+    "recated\030\001 \001(\010:\005false\022C\n\024uninterpreted_op"
+    "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+    "tedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031"
+    "\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterpret"
+    "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
+    "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptio"
+    "ns\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninter"
+    "preted_option\030\347\007 \003(\0132$.google.protobuf.U"
+    "ninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninte"
+    "rpretedOption\022;\n\004name\030\002 \003(\0132-.google.pro"
+    "tobuf.UninterpretedOption.NamePart\022\030\n\020id"
+    "entifier_value\030\003 \001(\t\022\032\n\022positive_int_val"
+    "ue\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014"
+    "double_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014"
+    "\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n"
+    "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325"
+    "\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(\0132(.go"
+    "ogle.protobuf.SourceCodeInfo.Location\032\206\001"
+    "\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003"
+    "(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trai"
+    "ling_comments\030\004 \001(\t\022!\n\031leading_detached_"
+    "comments\030\006 \003(\tB)\n\023com.google.protobufB\020D"
+    "escriptorProtosH\001", 4617);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
   FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -1009,6 +1013,40 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorSet
+
+// repeated .google.protobuf.FileDescriptorProto file = 1;
+ int FileDescriptorSet::file_size() const {
+  return file_.size();
+}
+ void FileDescriptorSet::clear_file() {
+  file_.Clear();
+}
+ const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file)
+  return file_.Get(index);
+}
+ ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file)
+  return file_.Mutable(index);
+}
+ ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
+  return file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+  return file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
+  return &file_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -1771,6 +1809,489 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorProto
+
+// optional string name = 1;
+ bool FileDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FileDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void FileDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void FileDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& FileDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
+}
+ ::std::string* FileDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
+}
+
+// optional string package = 2;
+ bool FileDescriptorProto::has_package() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FileDescriptorProto::set_has_package() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void FileDescriptorProto::clear_has_package() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void FileDescriptorProto::clear_package() {
+  package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_package();
+}
+ const ::std::string& FileDescriptorProto::package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
+  return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_package(const ::std::string& value) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value, size_t size) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
+}
+ ::std::string* FileDescriptorProto::mutable_package() {
+  set_has_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
+  return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_package() {
+  clear_has_package();
+  return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_package(::std::string* package) {
+  if (package != NULL) {
+    set_has_package();
+  } else {
+    clear_has_package();
+  }
+  package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
+}
+
+// repeated string dependency = 3;
+ int FileDescriptorProto::dependency_size() const {
+  return dependency_.size();
+}
+ void FileDescriptorProto::clear_dependency() {
+  dependency_.Clear();
+}
+ const ::std::string& FileDescriptorProto::dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Get(index);
+}
+ ::std::string* FileDescriptorProto::mutable_dependency(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Mutable(index);
+}
+ void FileDescriptorProto::set_dependency(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
+  dependency_.Mutable(index)->assign(value);
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value) {
+  dependency_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+  dependency_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ ::std::string* FileDescriptorProto::add_dependency() {
+  return dependency_.Add();
+}
+ void FileDescriptorProto::add_dependency(const ::std::string& value) {
+  dependency_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value) {
+  dependency_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+  dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency)
+  return &dependency_;
+}
+
+// repeated int32 public_dependency = 10;
+ int FileDescriptorProto::public_dependency_size() const {
+  return public_dependency_.size();
+}
+ void FileDescriptorProto::clear_public_dependency() {
+  public_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency)
+  return public_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+  public_dependency_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+  public_dependency_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency)
+  return public_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency)
+  return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+ int FileDescriptorProto::weak_dependency_size() const {
+  return weak_dependency_.size();
+}
+ void FileDescriptorProto::clear_weak_dependency() {
+  weak_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency)
+  return weak_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+  weak_dependency_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+  weak_dependency_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency)
+  return weak_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency)
+  return &weak_dependency_;
+}
+
+// repeated .google.protobuf.DescriptorProto message_type = 4;
+ int FileDescriptorProto::message_type_size() const {
+  return message_type_.size();
+}
+ void FileDescriptorProto::clear_message_type() {
+  message_type_.Clear();
+}
+ const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Get(index);
+}
+ ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
+  return &message_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+ int FileDescriptorProto::enum_type_size() const {
+  return enum_type_.size();
+}
+ void FileDescriptorProto::clear_enum_type() {
+  enum_type_.Clear();
+}
+ const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Get(index);
+}
+ ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Mutable(index);
+}
+ ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
+  return &enum_type_;
+}
+
+// repeated .google.protobuf.ServiceDescriptorProto service = 6;
+ int FileDescriptorProto::service_size() const {
+  return service_.size();
+}
+ void FileDescriptorProto::clear_service() {
+  service_.Clear();
+}
+ const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service)
+  return service_.Get(index);
+}
+ ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service)
+  return service_.Mutable(index);
+}
+ ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
+  return service_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+  return service_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
+  return &service_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 7;
+ int FileDescriptorProto::extension_size() const {
+  return extension_.size();
+}
+ void FileDescriptorProto::clear_extension() {
+  extension_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+  return extension_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
+  return &extension_;
+}
+
+// optional .google.protobuf.FileOptions options = 8;
+ bool FileDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+ void FileDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000200u;
+}
+ void FileDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+ void FileDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::FileOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::FileOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+ bool FileDescriptorProto::has_source_code_info() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+ void FileDescriptorProto::set_has_source_code_info() {
+  _has_bits_[0] |= 0x00000400u;
+}
+ void FileDescriptorProto::clear_has_source_code_info() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+ void FileDescriptorProto::clear_source_code_info() {
+  if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+  clear_has_source_code_info();
+}
+ const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
+  return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+ ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+  set_has_source_code_info();
+  if (source_code_info_ == NULL) {
+    source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
+  return source_code_info_;
+}
+ ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+  clear_has_source_code_info();
+  ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+  source_code_info_ = NULL;
+  return temp;
+}
+ void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+  delete source_code_info_;
+  source_code_info_ = source_code_info;
+  if (source_code_info) {
+    set_has_source_code_info();
+  } else {
+    clear_has_source_code_info();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
+}
+
+// optional string syntax = 12;
+ bool FileDescriptorProto::has_syntax() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+ void FileDescriptorProto::set_has_syntax() {
+  _has_bits_[0] |= 0x00000800u;
+}
+ void FileDescriptorProto::clear_has_syntax() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+ void FileDescriptorProto::clear_syntax() {
+  syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_syntax();
+}
+ const ::std::string& FileDescriptorProto::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
+  return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_syntax(const ::std::string& value) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value, size_t size) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+}
+ ::std::string* FileDescriptorProto::mutable_syntax() {
+  set_has_syntax();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
+  return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_syntax() {
+  clear_has_syntax();
+  return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) {
+  if (syntax != NULL) {
+    set_has_syntax();
+  } else {
+    clear_has_syntax();
+  }
+  syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -1839,19 +2360,17 @@
 }
 
 void DescriptorProto_ExtensionRange::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   ZR_(start_, end_);
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -2594,6 +3113,338 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// DescriptorProto_ExtensionRange
+
+// optional int32 start = 1;
+ bool DescriptorProto_ExtensionRange::has_start() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void DescriptorProto_ExtensionRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void DescriptorProto_ExtensionRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void DescriptorProto_ExtensionRange::clear_start() {
+  start_ = 0;
+  clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start)
+  return start_;
+}
+ void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
+  set_has_start();
+  start_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
+}
+
+// optional int32 end = 2;
+ bool DescriptorProto_ExtensionRange::has_end() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void DescriptorProto_ExtensionRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void DescriptorProto_ExtensionRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void DescriptorProto_ExtensionRange::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end)
+  return end_;
+}
+ void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto
+
+// optional string name = 1;
+ bool DescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void DescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void DescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void DescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& DescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
+}
+ ::std::string* DescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* DescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
+}
+
+// repeated .google.protobuf.FieldDescriptorProto field = 2;
+ int DescriptorProto::field_size() const {
+  return field_.size();
+}
+ void DescriptorProto::clear_field() {
+  field_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field)
+  return field_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field)
+  return field_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
+  return field_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+  return field_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
+  return &field_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 6;
+ int DescriptorProto::extension_size() const {
+  return extension_.size();
+}
+ void DescriptorProto::clear_extension() {
+  extension_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension)
+  return extension_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension)
+  return extension_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
+  return extension_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+  return extension_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
+  return &extension_;
+}
+
+// repeated .google.protobuf.DescriptorProto nested_type = 3;
+ int DescriptorProto::nested_type_size() const {
+  return nested_type_.size();
+}
+ void DescriptorProto::clear_nested_type() {
+  nested_type_.Clear();
+}
+ const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Get(index);
+}
+ ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
+  return &nested_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+ int DescriptorProto::enum_type_size() const {
+  return enum_type_.size();
+}
+ void DescriptorProto::clear_enum_type() {
+  enum_type_.Clear();
+}
+ const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Get(index);
+}
+ ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Mutable(index);
+}
+ ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
+  return &enum_type_;
+}
+
+// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+ int DescriptorProto::extension_range_size() const {
+  return extension_range_.size();
+}
+ void DescriptorProto::clear_extension_range() {
+  extension_range_.Clear();
+}
+ const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Get(index);
+}
+ ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
+  return &extension_range_;
+}
+
+// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+ int DescriptorProto::oneof_decl_size() const {
+  return oneof_decl_.size();
+}
+ void DescriptorProto::clear_oneof_decl() {
+  oneof_decl_.Clear();
+}
+ const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Get(index);
+}
+ ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Mutable(index);
+}
+ ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+DescriptorProto::mutable_oneof_decl() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
+  return &oneof_decl_;
+}
+
+// optional .google.protobuf.MessageOptions options = 7;
+ bool DescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+ void DescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+ void DescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+ void DescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::MessageOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::MessageOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -3308,6 +4159,363 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldDescriptorProto
+
+// optional string name = 1;
+ bool FieldDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FieldDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void FieldDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void FieldDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& FieldDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
+}
+ ::std::string* FieldDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
+}
+
+// optional int32 number = 3;
+ bool FieldDescriptorProto::has_number() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FieldDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void FieldDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void FieldDescriptorProto::clear_number() {
+  number_ = 0;
+  clear_has_number();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number)
+  return number_;
+}
+ void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
+  set_has_number();
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+ bool FieldDescriptorProto::has_label() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void FieldDescriptorProto::set_has_label() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void FieldDescriptorProto::clear_has_label() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void FieldDescriptorProto::clear_label() {
+  label_ = 1;
+  clear_has_label();
+}
+ ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label)
+  return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
+}
+ void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
+  assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+  set_has_label();
+  label_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+ bool FieldDescriptorProto::has_type() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void FieldDescriptorProto::set_has_type() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void FieldDescriptorProto::clear_has_type() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void FieldDescriptorProto::clear_type() {
+  type_ = 1;
+  clear_has_type();
+}
+ ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type)
+  return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
+}
+ void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
+  assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+  set_has_type();
+  type_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type)
+}
+
+// optional string type_name = 6;
+ bool FieldDescriptorProto::has_type_name() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void FieldDescriptorProto::set_has_type_name() {
+  _has_bits_[0] |= 0x00000010u;
+}
+ void FieldDescriptorProto::clear_has_type_name() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+ void FieldDescriptorProto::clear_type_name() {
+  type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_type_name();
+}
+ const ::std::string& FieldDescriptorProto::type_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
+  return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_type_name(const ::std::string& value) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
+}
+ ::std::string* FieldDescriptorProto::mutable_type_name() {
+  set_has_type_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
+  return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_type_name() {
+  clear_has_type_name();
+  return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+  if (type_name != NULL) {
+    set_has_type_name();
+  } else {
+    clear_has_type_name();
+  }
+  type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
+}
+
+// optional string extendee = 2;
+ bool FieldDescriptorProto::has_extendee() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void FieldDescriptorProto::set_has_extendee() {
+  _has_bits_[0] |= 0x00000020u;
+}
+ void FieldDescriptorProto::clear_has_extendee() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+ void FieldDescriptorProto::clear_extendee() {
+  extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_extendee();
+}
+ const ::std::string& FieldDescriptorProto::extendee() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
+  return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_extendee(const ::std::string& value) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
+}
+ ::std::string* FieldDescriptorProto::mutable_extendee() {
+  set_has_extendee();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
+  return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_extendee() {
+  clear_has_extendee();
+  return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+  if (extendee != NULL) {
+    set_has_extendee();
+  } else {
+    clear_has_extendee();
+  }
+  extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
+}
+
+// optional string default_value = 7;
+ bool FieldDescriptorProto::has_default_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+ void FieldDescriptorProto::set_has_default_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+ void FieldDescriptorProto::clear_has_default_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+ void FieldDescriptorProto::clear_default_value() {
+  default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_default_value();
+}
+ const ::std::string& FieldDescriptorProto::default_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
+  return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_default_value(const ::std::string& value) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
+}
+ ::std::string* FieldDescriptorProto::mutable_default_value() {
+  set_has_default_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
+  return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_default_value() {
+  clear_has_default_value();
+  return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+  if (default_value != NULL) {
+    set_has_default_value();
+  } else {
+    clear_has_default_value();
+  }
+  default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
+}
+
+// optional int32 oneof_index = 9;
+ bool FieldDescriptorProto::has_oneof_index() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+ void FieldDescriptorProto::set_has_oneof_index() {
+  _has_bits_[0] |= 0x00000080u;
+}
+ void FieldDescriptorProto::clear_has_oneof_index() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+ void FieldDescriptorProto::clear_oneof_index() {
+  oneof_index_ = 0;
+  clear_has_oneof_index();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index)
+  return oneof_index_;
+}
+ void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) {
+  set_has_oneof_index();
+  oneof_index_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
+}
+
+// optional .google.protobuf.FieldOptions options = 8;
+ bool FieldDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+ void FieldDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000100u;
+}
+ void FieldDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+ void FieldDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::FieldOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::FieldOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -3557,6 +4765,63 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// OneofDescriptorProto
+
+// optional string name = 1;
+ bool OneofDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void OneofDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void OneofDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void OneofDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& OneofDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
+}
+ ::std::string* OneofDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* OneofDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -3897,6 +5162,136 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumDescriptorProto
+
+// optional string name = 1;
+ bool EnumDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void EnumDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& EnumDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
+}
+ ::std::string* EnumDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
+}
+
+// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+ int EnumDescriptorProto::value_size() const {
+  return value_.size();
+}
+ void EnumDescriptorProto::clear_value() {
+  value_.Clear();
+}
+ const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value)
+  return value_.Get(index);
+}
+ ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value)
+  return value_.Mutable(index);
+}
+ ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
+  return value_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+  return value_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
+  return &value_;
+}
+
+// optional .google.protobuf.EnumOptions options = 3;
+ bool EnumDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void EnumDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void EnumDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void EnumDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::EnumOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::EnumOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -4236,6 +5631,130 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueDescriptorProto
+
+// optional string name = 1;
+ bool EnumValueDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumValueDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void EnumValueDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumValueDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& EnumValueDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
+}
+ ::std::string* EnumValueDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumValueDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
+}
+
+// optional int32 number = 2;
+ bool EnumValueDescriptorProto::has_number() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void EnumValueDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void EnumValueDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void EnumValueDescriptorProto::clear_number() {
+  number_ = 0;
+  clear_has_number();
+}
+ ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number)
+  return number_;
+}
+ void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
+  set_has_number();
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
+}
+
+// optional .google.protobuf.EnumValueOptions options = 3;
+ bool EnumValueDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void EnumValueDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void EnumValueDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void EnumValueDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::EnumValueOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::EnumValueOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -4576,6 +6095,136 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceDescriptorProto
+
+// optional string name = 1;
+ bool ServiceDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void ServiceDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void ServiceDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void ServiceDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& ServiceDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
+}
+ ::std::string* ServiceDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* ServiceDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
+}
+
+// repeated .google.protobuf.MethodDescriptorProto method = 2;
+ int ServiceDescriptorProto::method_size() const {
+  return method_.size();
+}
+ void ServiceDescriptorProto::clear_method() {
+  method_.Clear();
+}
+ const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Get(index);
+}
+ ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Mutable(index);
+}
+ ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+  return method_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
+  return &method_;
+}
+
+// optional .google.protobuf.ServiceOptions options = 3;
+ bool ServiceDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void ServiceDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void ServiceDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void ServiceDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::ServiceOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::ServiceOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -4658,15 +6307,13 @@
 }
 
 void MethodDescriptorProto::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<MethodDescriptorProto*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<MethodDescriptorProto*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   if (_has_bits_[0 / 32] & 63) {
     ZR_(client_streaming_, server_streaming_);
@@ -4684,7 +6331,7 @@
     }
   }
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -5075,6 +6722,260 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodDescriptorProto
+
+// optional string name = 1;
+ bool MethodDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void MethodDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void MethodDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void MethodDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& MethodDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
+}
+ ::std::string* MethodDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_name() {
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
+}
+
+// optional string input_type = 2;
+ bool MethodDescriptorProto::has_input_type() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void MethodDescriptorProto::set_has_input_type() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void MethodDescriptorProto::clear_has_input_type() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void MethodDescriptorProto::clear_input_type() {
+  input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_input_type();
+}
+ const ::std::string& MethodDescriptorProto::input_type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
+  return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_input_type(const ::std::string& value) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_input_type() {
+  set_has_input_type();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
+  return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_input_type() {
+  clear_has_input_type();
+  return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+  if (input_type != NULL) {
+    set_has_input_type();
+  } else {
+    clear_has_input_type();
+  }
+  input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
+}
+
+// optional string output_type = 3;
+ bool MethodDescriptorProto::has_output_type() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void MethodDescriptorProto::set_has_output_type() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void MethodDescriptorProto::clear_has_output_type() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void MethodDescriptorProto::clear_output_type() {
+  output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_output_type();
+}
+ const ::std::string& MethodDescriptorProto::output_type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
+  return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_output_type(const ::std::string& value) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_output_type() {
+  set_has_output_type();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
+  return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_output_type() {
+  clear_has_output_type();
+  return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+  if (output_type != NULL) {
+    set_has_output_type();
+  } else {
+    clear_has_output_type();
+  }
+  output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
+}
+
+// optional .google.protobuf.MethodOptions options = 4;
+ bool MethodDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void MethodDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void MethodDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void MethodDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
+  clear_has_options();
+}
+ const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::MethodOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
+  return options_;
+}
+ ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::MethodOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+ void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
+}
+
+// optional bool client_streaming = 5 [default = false];
+ bool MethodDescriptorProto::has_client_streaming() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void MethodDescriptorProto::set_has_client_streaming() {
+  _has_bits_[0] |= 0x00000010u;
+}
+ void MethodDescriptorProto::clear_has_client_streaming() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+ void MethodDescriptorProto::clear_client_streaming() {
+  client_streaming_ = false;
+  clear_has_client_streaming();
+}
+ bool MethodDescriptorProto::client_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming)
+  return client_streaming_;
+}
+ void MethodDescriptorProto::set_client_streaming(bool value) {
+  set_has_client_streaming();
+  client_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming)
+}
+
+// optional bool server_streaming = 6 [default = false];
+ bool MethodDescriptorProto::has_server_streaming() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void MethodDescriptorProto::set_has_server_streaming() {
+  _has_bits_[0] |= 0x00000020u;
+}
+ void MethodDescriptorProto::clear_has_server_streaming() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+ void MethodDescriptorProto::clear_server_streaming() {
+  server_streaming_ = false;
+  clear_has_server_streaming();
+}
+ bool MethodDescriptorProto::server_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming)
+  return server_streaming_;
+}
+ void MethodDescriptorProto::set_server_streaming(bool value) {
+  set_has_server_streaming();
+  server_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -5114,6 +7015,7 @@
 const int FileOptions::kPyGenericServicesFieldNumber;
 const int FileOptions::kDeprecatedFieldNumber;
 const int FileOptions::kCcEnableArenasFieldNumber;
+const int FileOptions::kObjcClassPrefixFieldNumber;
 const int FileOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
@@ -5149,6 +7051,7 @@
   py_generic_services_ = false;
   deprecated_ = false;
   cc_enable_arenas_ = false;
+  objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -5161,6 +7064,7 @@
   java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   if (this != default_instance_) {
   }
 }
@@ -5192,15 +7096,13 @@
 
 void FileOptions::Clear() {
   _extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<FileOptions*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<FileOptions*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   if (_has_bits_[0 / 32] & 255) {
     ZR_(java_multiple_files_, cc_generic_services_);
@@ -5215,9 +7117,14 @@
       go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
     }
   }
-  ZR_(java_generic_services_, cc_enable_arenas_);
+  if (_has_bits_[8 / 32] & 7936) {
+    ZR_(java_generic_services_, cc_enable_arenas_);
+    if (has_objc_class_prefix()) {
+      objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   uninterpreted_option_.Clear();
@@ -5423,6 +7330,23 @@
         } else {
           goto handle_unusual;
         }
+        if (input->ExpectTag(290)) goto parse_objc_class_prefix;
+        break;
+      }
+
+      // optional string objc_class_prefix = 36;
+      case 36: {
+        if (tag == 290) {
+         parse_objc_class_prefix:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_objc_class_prefix()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.objc_class_prefix");
+        } else {
+          goto handle_unusual;
+        }
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
@@ -5547,6 +7471,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output);
   }
 
+  // optional string objc_class_prefix = 36;
+  if (has_objc_class_prefix()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.objc_class_prefix");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      36, this->objc_class_prefix(), output);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -5646,6 +7580,17 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target);
   }
 
+  // optional string objc_class_prefix = 36;
+  if (has_objc_class_prefix()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.objc_class_prefix");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        36, this->objc_class_prefix(), target);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
@@ -5717,7 +7662,7 @@
     }
 
   }
-  if (_has_bits_[8 / 32] & 3840) {
+  if (_has_bits_[8 / 32] & 7936) {
     // optional bool java_generic_services = 17 [default = false];
     if (has_java_generic_services()) {
       total_size += 2 + 1;
@@ -5738,6 +7683,13 @@
       total_size += 2 + 1;
     }
 
+    // optional string objc_class_prefix = 36;
+    if (has_objc_class_prefix()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->objc_class_prefix());
+    }
+
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
@@ -5817,6 +7769,10 @@
     if (from.has_cc_enable_arenas()) {
       set_cc_enable_arenas(from.cc_enable_arenas());
     }
+    if (from.has_objc_class_prefix()) {
+      set_has_objc_class_prefix();
+      objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_);
+    }
   }
   _extensions_.MergeFrom(from._extensions_);
   if (from._internal_metadata_.have_unknown_fields()) {
@@ -5860,6 +7816,7 @@
   std::swap(py_generic_services_, other->py_generic_services_);
   std::swap(deprecated_, other->deprecated_);
   std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
+  objc_class_prefix_.Swap(&other->objc_class_prefix_);
   uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
   std::swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
@@ -5875,6 +7832,469 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileOptions
+
+// optional string java_package = 1;
+ bool FileOptions::has_java_package() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FileOptions::set_has_java_package() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void FileOptions::clear_has_java_package() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void FileOptions::clear_java_package() {
+  java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_java_package();
+}
+ const ::std::string& FileOptions::java_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
+  return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_package(const ::std::string& value) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value, size_t size) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
+}
+ ::std::string* FileOptions::mutable_java_package() {
+  set_has_java_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
+  return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_package() {
+  clear_has_java_package();
+  return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_package(::std::string* java_package) {
+  if (java_package != NULL) {
+    set_has_java_package();
+  } else {
+    clear_has_java_package();
+  }
+  java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
+}
+
+// optional string java_outer_classname = 8;
+ bool FileOptions::has_java_outer_classname() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FileOptions::set_has_java_outer_classname() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void FileOptions::clear_has_java_outer_classname() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void FileOptions::clear_java_outer_classname() {
+  java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_java_outer_classname();
+}
+ const ::std::string& FileOptions::java_outer_classname() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
+  return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_outer_classname(const ::std::string& value) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value, size_t size) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
+}
+ ::std::string* FileOptions::mutable_java_outer_classname() {
+  set_has_java_outer_classname();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
+  return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_outer_classname() {
+  clear_has_java_outer_classname();
+  return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+  if (java_outer_classname != NULL) {
+    set_has_java_outer_classname();
+  } else {
+    clear_has_java_outer_classname();
+  }
+  java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
+}
+
+// optional bool java_multiple_files = 10 [default = false];
+ bool FileOptions::has_java_multiple_files() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void FileOptions::set_has_java_multiple_files() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void FileOptions::clear_has_java_multiple_files() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void FileOptions::clear_java_multiple_files() {
+  java_multiple_files_ = false;
+  clear_has_java_multiple_files();
+}
+ bool FileOptions::java_multiple_files() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files)
+  return java_multiple_files_;
+}
+ void FileOptions::set_java_multiple_files(bool value) {
+  set_has_java_multiple_files();
+  java_multiple_files_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files)
+}
+
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+ bool FileOptions::has_java_generate_equals_and_hash() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void FileOptions::set_has_java_generate_equals_and_hash() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void FileOptions::clear_has_java_generate_equals_and_hash() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void FileOptions::clear_java_generate_equals_and_hash() {
+  java_generate_equals_and_hash_ = false;
+  clear_has_java_generate_equals_and_hash();
+}
+ bool FileOptions::java_generate_equals_and_hash() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash)
+  return java_generate_equals_and_hash_;
+}
+ void FileOptions::set_java_generate_equals_and_hash(bool value) {
+  set_has_java_generate_equals_and_hash();
+  java_generate_equals_and_hash_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash)
+}
+
+// optional bool java_string_check_utf8 = 27 [default = false];
+ bool FileOptions::has_java_string_check_utf8() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void FileOptions::set_has_java_string_check_utf8() {
+  _has_bits_[0] |= 0x00000010u;
+}
+ void FileOptions::clear_has_java_string_check_utf8() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+ void FileOptions::clear_java_string_check_utf8() {
+  java_string_check_utf8_ = false;
+  clear_has_java_string_check_utf8();
+}
+ bool FileOptions::java_string_check_utf8() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8)
+  return java_string_check_utf8_;
+}
+ void FileOptions::set_java_string_check_utf8(bool value) {
+  set_has_java_string_check_utf8();
+  java_string_check_utf8_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8)
+}
+
+// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+ bool FileOptions::has_optimize_for() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void FileOptions::set_has_optimize_for() {
+  _has_bits_[0] |= 0x00000020u;
+}
+ void FileOptions::clear_has_optimize_for() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+ void FileOptions::clear_optimize_for() {
+  optimize_for_ = 1;
+  clear_has_optimize_for();
+}
+ ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for)
+  return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
+}
+ void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
+  assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+  set_has_optimize_for();
+  optimize_for_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for)
+}
+
+// optional string go_package = 11;
+ bool FileOptions::has_go_package() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+ void FileOptions::set_has_go_package() {
+  _has_bits_[0] |= 0x00000040u;
+}
+ void FileOptions::clear_has_go_package() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+ void FileOptions::clear_go_package() {
+  go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_go_package();
+}
+ const ::std::string& FileOptions::go_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
+  return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_go_package(const ::std::string& value) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value, size_t size) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
+}
+ ::std::string* FileOptions::mutable_go_package() {
+  set_has_go_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
+  return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_go_package() {
+  clear_has_go_package();
+  return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_go_package(::std::string* go_package) {
+  if (go_package != NULL) {
+    set_has_go_package();
+  } else {
+    clear_has_go_package();
+  }
+  go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+ bool FileOptions::has_cc_generic_services() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+ void FileOptions::set_has_cc_generic_services() {
+  _has_bits_[0] |= 0x00000080u;
+}
+ void FileOptions::clear_has_cc_generic_services() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+ void FileOptions::clear_cc_generic_services() {
+  cc_generic_services_ = false;
+  clear_has_cc_generic_services();
+}
+ bool FileOptions::cc_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services)
+  return cc_generic_services_;
+}
+ void FileOptions::set_cc_generic_services(bool value) {
+  set_has_cc_generic_services();
+  cc_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services)
+}
+
+// optional bool java_generic_services = 17 [default = false];
+ bool FileOptions::has_java_generic_services() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+ void FileOptions::set_has_java_generic_services() {
+  _has_bits_[0] |= 0x00000100u;
+}
+ void FileOptions::clear_has_java_generic_services() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+ void FileOptions::clear_java_generic_services() {
+  java_generic_services_ = false;
+  clear_has_java_generic_services();
+}
+ bool FileOptions::java_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services)
+  return java_generic_services_;
+}
+ void FileOptions::set_java_generic_services(bool value) {
+  set_has_java_generic_services();
+  java_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services)
+}
+
+// optional bool py_generic_services = 18 [default = false];
+ bool FileOptions::has_py_generic_services() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+ void FileOptions::set_has_py_generic_services() {
+  _has_bits_[0] |= 0x00000200u;
+}
+ void FileOptions::clear_has_py_generic_services() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+ void FileOptions::clear_py_generic_services() {
+  py_generic_services_ = false;
+  clear_has_py_generic_services();
+}
+ bool FileOptions::py_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services)
+  return py_generic_services_;
+}
+ void FileOptions::set_py_generic_services(bool value) {
+  set_has_py_generic_services();
+  py_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
+}
+
+// optional bool deprecated = 23 [default = false];
+ bool FileOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+ void FileOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000400u;
+}
+ void FileOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+ void FileOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool FileOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated)
+  return deprecated_;
+}
+ void FileOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated)
+}
+
+// optional bool cc_enable_arenas = 31 [default = false];
+ bool FileOptions::has_cc_enable_arenas() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+ void FileOptions::set_has_cc_enable_arenas() {
+  _has_bits_[0] |= 0x00000800u;
+}
+ void FileOptions::clear_has_cc_enable_arenas() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+ void FileOptions::clear_cc_enable_arenas() {
+  cc_enable_arenas_ = false;
+  clear_has_cc_enable_arenas();
+}
+ bool FileOptions::cc_enable_arenas() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas)
+  return cc_enable_arenas_;
+}
+ void FileOptions::set_cc_enable_arenas(bool value) {
+  set_has_cc_enable_arenas();
+  cc_enable_arenas_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
+}
+
+// optional string objc_class_prefix = 36;
+ bool FileOptions::has_objc_class_prefix() const {
+  return (_has_bits_[0] & 0x00001000u) != 0;
+}
+ void FileOptions::set_has_objc_class_prefix() {
+  _has_bits_[0] |= 0x00001000u;
+}
+ void FileOptions::clear_has_objc_class_prefix() {
+  _has_bits_[0] &= ~0x00001000u;
+}
+ void FileOptions::clear_objc_class_prefix() {
+  objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_objc_class_prefix();
+}
+ const ::std::string& FileOptions::objc_class_prefix() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+ ::std::string* FileOptions::mutable_objc_class_prefix() {
+  set_has_objc_class_prefix();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_objc_class_prefix() {
+  clear_has_objc_class_prefix();
+  return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+  if (objc_class_prefix != NULL) {
+    set_has_objc_class_prefix();
+  } else {
+    clear_has_objc_class_prefix();
+  }
+  objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int FileOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void FileOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -5949,19 +8369,17 @@
 
 void MessageOptions::Clear() {
   _extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<MessageOptions*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<MessageOptions*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   ZR_(message_set_wire_format_, map_entry_);
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   uninterpreted_option_.Clear();
@@ -6287,6 +8705,136 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MessageOptions
+
+// optional bool message_set_wire_format = 1 [default = false];
+ bool MessageOptions::has_message_set_wire_format() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void MessageOptions::set_has_message_set_wire_format() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void MessageOptions::clear_has_message_set_wire_format() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void MessageOptions::clear_message_set_wire_format() {
+  message_set_wire_format_ = false;
+  clear_has_message_set_wire_format();
+}
+ bool MessageOptions::message_set_wire_format() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format)
+  return message_set_wire_format_;
+}
+ void MessageOptions::set_message_set_wire_format(bool value) {
+  set_has_message_set_wire_format();
+  message_set_wire_format_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format)
+}
+
+// optional bool no_standard_descriptor_accessor = 2 [default = false];
+ bool MessageOptions::has_no_standard_descriptor_accessor() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void MessageOptions::set_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void MessageOptions::clear_no_standard_descriptor_accessor() {
+  no_standard_descriptor_accessor_ = false;
+  clear_has_no_standard_descriptor_accessor();
+}
+ bool MessageOptions::no_standard_descriptor_accessor() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+  return no_standard_descriptor_accessor_;
+}
+ void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
+  set_has_no_standard_descriptor_accessor();
+  no_standard_descriptor_accessor_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+}
+
+// optional bool deprecated = 3 [default = false];
+ bool MessageOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void MessageOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void MessageOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void MessageOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool MessageOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated)
+  return deprecated_;
+}
+ void MessageOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated)
+}
+
+// optional bool map_entry = 7;
+ bool MessageOptions::has_map_entry() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void MessageOptions::set_has_map_entry() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void MessageOptions::clear_has_map_entry() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void MessageOptions::clear_map_entry() {
+  map_entry_ = false;
+  clear_has_map_entry();
+}
+ bool MessageOptions::map_entry() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry)
+  return map_entry_;
+}
+ void MessageOptions::set_map_entry(bool value) {
+  set_has_map_entry();
+  map_entry_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int MessageOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void MessageOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -6386,21 +8934,19 @@
 
 void FieldOptions::Clear() {
   _extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<FieldOptions*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<FieldOptions*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   if (_has_bits_[0 / 32] & 31) {
     ZR_(ctype_, weak_);
   }
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   uninterpreted_option_.Clear();
@@ -6768,6 +9314,161 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldOptions
+
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+ bool FieldOptions::has_ctype() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FieldOptions::set_has_ctype() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void FieldOptions::clear_has_ctype() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void FieldOptions::clear_ctype() {
+  ctype_ = 0;
+  clear_has_ctype();
+}
+ ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype)
+  return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
+}
+ void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
+  assert(::google::protobuf::FieldOptions_CType_IsValid(value));
+  set_has_ctype();
+  ctype_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype)
+}
+
+// optional bool packed = 2;
+ bool FieldOptions::has_packed() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FieldOptions::set_has_packed() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void FieldOptions::clear_has_packed() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void FieldOptions::clear_packed() {
+  packed_ = false;
+  clear_has_packed();
+}
+ bool FieldOptions::packed() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed)
+  return packed_;
+}
+ void FieldOptions::set_packed(bool value) {
+  set_has_packed();
+  packed_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
+}
+
+// optional bool lazy = 5 [default = false];
+ bool FieldOptions::has_lazy() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void FieldOptions::set_has_lazy() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void FieldOptions::clear_has_lazy() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void FieldOptions::clear_lazy() {
+  lazy_ = false;
+  clear_has_lazy();
+}
+ bool FieldOptions::lazy() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy)
+  return lazy_;
+}
+ void FieldOptions::set_lazy(bool value) {
+  set_has_lazy();
+  lazy_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy)
+}
+
+// optional bool deprecated = 3 [default = false];
+ bool FieldOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void FieldOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void FieldOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void FieldOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool FieldOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated)
+  return deprecated_;
+}
+ void FieldOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
+}
+
+// optional bool weak = 10 [default = false];
+ bool FieldOptions::has_weak() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void FieldOptions::set_has_weak() {
+  _has_bits_[0] |= 0x00000010u;
+}
+ void FieldOptions::clear_has_weak() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+ void FieldOptions::clear_weak() {
+  weak_ = false;
+  clear_has_weak();
+}
+ bool FieldOptions::weak() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak)
+  return weak_;
+}
+ void FieldOptions::set_weak(bool value) {
+  set_has_weak();
+  weak_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int FieldOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void FieldOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -6838,19 +9539,17 @@
 
 void EnumOptions::Clear() {
   _extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<EnumOptions*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<EnumOptions*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   ZR_(allow_alias_, deprecated_);
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   uninterpreted_option_.Clear();
@@ -7108,6 +9807,88 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumOptions
+
+// optional bool allow_alias = 2;
+ bool EnumOptions::has_allow_alias() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumOptions::set_has_allow_alias() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void EnumOptions::clear_has_allow_alias() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumOptions::clear_allow_alias() {
+  allow_alias_ = false;
+  clear_has_allow_alias();
+}
+ bool EnumOptions::allow_alias() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias)
+  return allow_alias_;
+}
+ void EnumOptions::set_allow_alias(bool value) {
+  set_has_allow_alias();
+  allow_alias_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias)
+}
+
+// optional bool deprecated = 3 [default = false];
+ bool EnumOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void EnumOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void EnumOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void EnumOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool EnumOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated)
+  return deprecated_;
+}
+ void EnumOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int EnumOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void EnumOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -7396,6 +10177,64 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueOptions
+
+// optional bool deprecated = 1 [default = false];
+ bool EnumValueOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumValueOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void EnumValueOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumValueOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool EnumValueOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated)
+  return deprecated_;
+}
+ void EnumValueOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int EnumValueOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void EnumValueOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -7684,6 +10523,64 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceOptions
+
+// optional bool deprecated = 33 [default = false];
+ bool ServiceOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void ServiceOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void ServiceOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void ServiceOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool ServiceOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated)
+  return deprecated_;
+}
+ void ServiceOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int ServiceOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void ServiceOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -7972,6 +10869,64 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodOptions
+
+// optional bool deprecated = 33 [default = false];
+ bool MethodOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void MethodOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void MethodOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void MethodOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool MethodOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated)
+  return deprecated_;
+}
+ void MethodOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int MethodOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+ void MethodOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -8359,15 +11314,13 @@
 }
 
 void UninterpretedOption::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
-  &reinterpret_cast<UninterpretedOption*>(16)->f) - \
-   reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<UninterpretedOption*>(16)->f)
 
-#define ZR_(first, last) do {                              \
-    size_t f = OFFSET_OF_FIELD_(first);                    \
-    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
-    ::memset(&first, 0, n);                                \
-  } while (0)
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
 
   if (_has_bits_[0 / 32] & 126) {
     ZR_(positive_int_value_, double_value_);
@@ -8382,7 +11335,7 @@
     }
   }
 
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
 #undef ZR_
 
   name_.Clear();
@@ -8799,6 +11752,352 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UninterpretedOption_NamePart
+
+// required string name_part = 1;
+ bool UninterpretedOption_NamePart::has_name_part() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void UninterpretedOption_NamePart::set_has_name_part() {
+  _has_bits_[0] |= 0x00000001u;
+}
+ void UninterpretedOption_NamePart::clear_has_name_part() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+ void UninterpretedOption_NamePart::clear_name_part() {
+  name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name_part();
+}
+ const ::std::string& UninterpretedOption_NamePart::name_part() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
+  return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
+  set_has_name_part();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
+  return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption_NamePart::release_name_part() {
+  clear_has_name_part();
+  return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+  if (name_part != NULL) {
+    set_has_name_part();
+  } else {
+    clear_has_name_part();
+  }
+  name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+
+// required bool is_extension = 2;
+ bool UninterpretedOption_NamePart::has_is_extension() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void UninterpretedOption_NamePart::set_has_is_extension() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void UninterpretedOption_NamePart::clear_has_is_extension() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void UninterpretedOption_NamePart::clear_is_extension() {
+  is_extension_ = false;
+  clear_has_is_extension();
+}
+ bool UninterpretedOption_NamePart::is_extension() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension)
+  return is_extension_;
+}
+ void UninterpretedOption_NamePart::set_is_extension(bool value) {
+  set_has_is_extension();
+  is_extension_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension)
+}
+
+// -------------------------------------------------------------------
+
+// UninterpretedOption
+
+// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+ int UninterpretedOption::name_size() const {
+  return name_.size();
+}
+ void UninterpretedOption::clear_name() {
+  name_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name)
+  return name_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name)
+  return name_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+  // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
+  return name_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+  return name_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
+  return &name_;
+}
+
+// optional string identifier_value = 3;
+ bool UninterpretedOption::has_identifier_value() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void UninterpretedOption::set_has_identifier_value() {
+  _has_bits_[0] |= 0x00000002u;
+}
+ void UninterpretedOption::clear_has_identifier_value() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+ void UninterpretedOption::clear_identifier_value() {
+  identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_identifier_value();
+}
+ const ::std::string& UninterpretedOption::identifier_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
+  return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_identifier_value(const ::std::string& value) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
+}
+ ::std::string* UninterpretedOption::mutable_identifier_value() {
+  set_has_identifier_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
+  return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_identifier_value() {
+  clear_has_identifier_value();
+  return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+  if (identifier_value != NULL) {
+    set_has_identifier_value();
+  } else {
+    clear_has_identifier_value();
+  }
+  identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
+}
+
+// optional uint64 positive_int_value = 4;
+ bool UninterpretedOption::has_positive_int_value() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void UninterpretedOption::set_has_positive_int_value() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void UninterpretedOption::clear_has_positive_int_value() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void UninterpretedOption::clear_positive_int_value() {
+  positive_int_value_ = GOOGLE_ULONGLONG(0);
+  clear_has_positive_int_value();
+}
+ ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value)
+  return positive_int_value_;
+}
+ void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
+  set_has_positive_int_value();
+  positive_int_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value)
+}
+
+// optional int64 negative_int_value = 5;
+ bool UninterpretedOption::has_negative_int_value() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void UninterpretedOption::set_has_negative_int_value() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void UninterpretedOption::clear_has_negative_int_value() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void UninterpretedOption::clear_negative_int_value() {
+  negative_int_value_ = GOOGLE_LONGLONG(0);
+  clear_has_negative_int_value();
+}
+ ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value)
+  return negative_int_value_;
+}
+ void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
+  set_has_negative_int_value();
+  negative_int_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
+}
+
+// optional double double_value = 6;
+ bool UninterpretedOption::has_double_value() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void UninterpretedOption::set_has_double_value() {
+  _has_bits_[0] |= 0x00000010u;
+}
+ void UninterpretedOption::clear_has_double_value() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+ void UninterpretedOption::clear_double_value() {
+  double_value_ = 0;
+  clear_has_double_value();
+}
+ double UninterpretedOption::double_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value)
+  return double_value_;
+}
+ void UninterpretedOption::set_double_value(double value) {
+  set_has_double_value();
+  double_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value)
+}
+
+// optional bytes string_value = 7;
+ bool UninterpretedOption::has_string_value() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void UninterpretedOption::set_has_string_value() {
+  _has_bits_[0] |= 0x00000020u;
+}
+ void UninterpretedOption::clear_has_string_value() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+ void UninterpretedOption::clear_string_value() {
+  string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_string_value();
+}
+ const ::std::string& UninterpretedOption::string_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
+  return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_string_value(const ::std::string& value) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const char* value) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const void* value, size_t size) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
+}
+ ::std::string* UninterpretedOption::mutable_string_value() {
+  set_has_string_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
+  return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_string_value() {
+  clear_has_string_value();
+  return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+  if (string_value != NULL) {
+    set_has_string_value();
+  } else {
+    clear_has_string_value();
+  }
+  string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
+}
+
+// optional string aggregate_value = 8;
+ bool UninterpretedOption::has_aggregate_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+ void UninterpretedOption::set_has_aggregate_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+ void UninterpretedOption::clear_has_aggregate_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+ void UninterpretedOption::clear_aggregate_value() {
+  aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_aggregate_value();
+}
+ const ::std::string& UninterpretedOption::aggregate_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
+  return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ ::std::string* UninterpretedOption::mutable_aggregate_value() {
+  set_has_aggregate_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
+  return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_aggregate_value() {
+  clear_has_aggregate_value();
+  return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+  if (aggregate_value != NULL) {
+    set_has_aggregate_value();
+  } else {
+    clear_has_aggregate_value();
+  }
+  aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
@@ -8807,6 +12106,7 @@
 const int SourceCodeInfo_Location::kSpanFieldNumber;
 const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber;
 const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber;
 #endif  // !_MSC_VER
 
 SourceCodeInfo_Location::SourceCodeInfo_Location()
@@ -8882,6 +12182,7 @@
   }
   path_.Clear();
   span_.Clear();
+  leading_detached_comments_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
   if (_internal_metadata_.have_unknown_fields()) {
     mutable_unknown_fields()->Clear();
@@ -8963,6 +12264,25 @@
         } else {
           goto handle_unusual;
         }
+        if (input->ExpectTag(50)) goto parse_leading_detached_comments;
+        break;
+      }
+
+      // repeated string leading_detached_comments = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_leading_detached_comments:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_leading_detached_comments()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(),
+            this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_leading_detached_comments;
         if (input->ExpectAtEnd()) goto success;
         break;
       }
@@ -9032,6 +12352,16 @@
       4, this->trailing_comments(), output);
   }
 
+  // repeated string leading_detached_comments = 6;
+  for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+  ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+    this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+    ::google::protobuf::internal::WireFormat::SERIALIZE,
+    "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      6, this->leading_detached_comments(i), output);
+  }
+
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
         unknown_fields(), output);
@@ -9092,6 +12422,16 @@
         4, this->trailing_comments(), target);
   }
 
+  // repeated string leading_detached_comments = 6;
+  for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(6, this->leading_detached_comments(i), target);
+  }
+
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -9153,6 +12493,13 @@
     total_size += data_size;
   }
 
+  // repeated string leading_detached_comments = 6;
+  total_size += 1 * this->leading_detached_comments_size();
+  for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->leading_detached_comments(i));
+  }
+
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@@ -9180,6 +12527,7 @@
   if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   path_.MergeFrom(from.path_);
   span_.MergeFrom(from.span_);
+  leading_detached_comments_.MergeFrom(from.leading_detached_comments_);
   if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) {
     if (from.has_leading_comments()) {
       set_has_leading_comments();
@@ -9221,6 +12569,7 @@
   span_.UnsafeArenaSwap(&other->span_);
   leading_comments_.Swap(&other->leading_comments_);
   trailing_comments_.Swap(&other->trailing_comments_);
+  leading_detached_comments_.UnsafeArenaSwap(&other->leading_detached_comments_);
   std::swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
   std::swap(_cached_size_, other->_cached_size_);
@@ -9464,6 +12813,264 @@
   return metadata;
 }
 
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+ int SourceCodeInfo_Location::path_size() const {
+  return path_.size();
+}
+ void SourceCodeInfo_Location::clear_path() {
+  path_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path)
+  return path_.Get(index);
+}
+ void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path)
+}
+ void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path)
+  return path_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path)
+  return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+ int SourceCodeInfo_Location::span_size() const {
+  return span_.size();
+}
+ void SourceCodeInfo_Location::clear_span() {
+  span_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span)
+  return span_.Get(index);
+}
+ void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+  span_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span)
+}
+ void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+  span_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span)
+  return span_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span)
+  return &span_;
+}
+
+// optional string leading_comments = 3;
+ bool SourceCodeInfo_Location::has_leading_comments() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void SourceCodeInfo_Location::set_has_leading_comments() {
+  _has_bits_[0] |= 0x00000004u;
+}
+ void SourceCodeInfo_Location::clear_has_leading_comments() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+ void SourceCodeInfo_Location::clear_leading_comments() {
+  leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_leading_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+  set_has_leading_comments();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+  clear_has_leading_comments();
+  return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+  if (leading_comments != NULL) {
+    set_has_leading_comments();
+  } else {
+    clear_has_leading_comments();
+  }
+  leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+
+// optional string trailing_comments = 4;
+ bool SourceCodeInfo_Location::has_trailing_comments() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void SourceCodeInfo_Location::set_has_trailing_comments() {
+  _has_bits_[0] |= 0x00000008u;
+}
+ void SourceCodeInfo_Location::clear_has_trailing_comments() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+ void SourceCodeInfo_Location::clear_trailing_comments() {
+  trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_trailing_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+  set_has_trailing_comments();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+  clear_has_trailing_comments();
+  return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+  if (trailing_comments != NULL) {
+    set_has_trailing_comments();
+  } else {
+    clear_has_trailing_comments();
+  }
+  trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+
+// repeated string leading_detached_comments = 6;
+ int SourceCodeInfo_Location::leading_detached_comments_size() const {
+  return leading_detached_comments_.size();
+}
+ void SourceCodeInfo_Location::clear_leading_detached_comments() {
+  leading_detached_comments_.Clear();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Get(index);
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Mutable(index);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  leading_detached_comments_.Mutable(index)->assign(value);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+  leading_detached_comments_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+  leading_detached_comments_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+  return leading_detached_comments_.Add();
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+  leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return &leading_detached_comments_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+ int SourceCodeInfo::location_size() const {
+  return location_.size();
+}
+ void SourceCodeInfo::clear_location() {
+  location_.Clear();
+}
+ const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location)
+  return location_.Get(index);
+}
+ ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location)
+  return location_.Mutable(index);
+}
+ ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
+  return location_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+  return location_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
+  return &location_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
 
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index cda2598..d8cba65 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -222,15 +222,15 @@
   // accessors -------------------------------------------------------
 
   // repeated .google.protobuf.FileDescriptorProto file = 1;
-  inline int file_size() const;
-  inline void clear_file();
+  int file_size() const;
+  void clear_file();
   static const int kFileFieldNumber = 1;
-  inline const ::google::protobuf::FileDescriptorProto& file(int index) const;
-  inline ::google::protobuf::FileDescriptorProto* mutable_file(int index);
-  inline ::google::protobuf::FileDescriptorProto* add_file();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+  const ::google::protobuf::FileDescriptorProto& file(int index) const;
+  ::google::protobuf::FileDescriptorProto* mutable_file(int index);
+  ::google::protobuf::FileDescriptorProto* add_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
       file() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
       mutable_file();
 
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
@@ -314,146 +314,146 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // optional string package = 2;
-  inline bool has_package() const;
-  inline void clear_package();
+  bool has_package() const;
+  void clear_package();
   static const int kPackageFieldNumber = 2;
-  inline const ::std::string& package() const;
-  inline void set_package(const ::std::string& value);
-  inline void set_package(const char* value);
-  inline void set_package(const char* value, size_t size);
-  inline ::std::string* mutable_package();
-  inline ::std::string* release_package();
-  inline void set_allocated_package(::std::string* package);
+  const ::std::string& package() const;
+  void set_package(const ::std::string& value);
+  void set_package(const char* value);
+  void set_package(const char* value, size_t size);
+  ::std::string* mutable_package();
+  ::std::string* release_package();
+  void set_allocated_package(::std::string* package);
 
   // repeated string dependency = 3;
-  inline int dependency_size() const;
-  inline void clear_dependency();
+  int dependency_size() const;
+  void clear_dependency();
   static const int kDependencyFieldNumber = 3;
-  inline const ::std::string& dependency(int index) const;
-  inline ::std::string* mutable_dependency(int index);
-  inline void set_dependency(int index, const ::std::string& value);
-  inline void set_dependency(int index, const char* value);
-  inline void set_dependency(int index, const char* value, size_t size);
-  inline ::std::string* add_dependency();
-  inline void add_dependency(const ::std::string& value);
-  inline void add_dependency(const char* value);
-  inline void add_dependency(const char* value, size_t size);
-  inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
-  inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
+  const ::std::string& dependency(int index) const;
+  ::std::string* mutable_dependency(int index);
+  void set_dependency(int index, const ::std::string& value);
+  void set_dependency(int index, const char* value);
+  void set_dependency(int index, const char* value, size_t size);
+  ::std::string* add_dependency();
+  void add_dependency(const ::std::string& value);
+  void add_dependency(const char* value);
+  void add_dependency(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
 
   // repeated int32 public_dependency = 10;
-  inline int public_dependency_size() const;
-  inline void clear_public_dependency();
+  int public_dependency_size() const;
+  void clear_public_dependency();
   static const int kPublicDependencyFieldNumber = 10;
-  inline ::google::protobuf::int32 public_dependency(int index) const;
-  inline void set_public_dependency(int index, ::google::protobuf::int32 value);
-  inline void add_public_dependency(::google::protobuf::int32 value);
-  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+  ::google::protobuf::int32 public_dependency(int index) const;
+  void set_public_dependency(int index, ::google::protobuf::int32 value);
+  void add_public_dependency(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
       public_dependency() const;
-  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
       mutable_public_dependency();
 
   // repeated int32 weak_dependency = 11;
-  inline int weak_dependency_size() const;
-  inline void clear_weak_dependency();
+  int weak_dependency_size() const;
+  void clear_weak_dependency();
   static const int kWeakDependencyFieldNumber = 11;
-  inline ::google::protobuf::int32 weak_dependency(int index) const;
-  inline void set_weak_dependency(int index, ::google::protobuf::int32 value);
-  inline void add_weak_dependency(::google::protobuf::int32 value);
-  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+  ::google::protobuf::int32 weak_dependency(int index) const;
+  void set_weak_dependency(int index, ::google::protobuf::int32 value);
+  void add_weak_dependency(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
       weak_dependency() const;
-  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
       mutable_weak_dependency();
 
   // repeated .google.protobuf.DescriptorProto message_type = 4;
-  inline int message_type_size() const;
-  inline void clear_message_type();
+  int message_type_size() const;
+  void clear_message_type();
   static const int kMessageTypeFieldNumber = 4;
-  inline const ::google::protobuf::DescriptorProto& message_type(int index) const;
-  inline ::google::protobuf::DescriptorProto* mutable_message_type(int index);
-  inline ::google::protobuf::DescriptorProto* add_message_type();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+  const ::google::protobuf::DescriptorProto& message_type(int index) const;
+  ::google::protobuf::DescriptorProto* mutable_message_type(int index);
+  ::google::protobuf::DescriptorProto* add_message_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
       message_type() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
       mutable_message_type();
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
-  inline int enum_type_size() const;
-  inline void clear_enum_type();
+  int enum_type_size() const;
+  void clear_enum_type();
   static const int kEnumTypeFieldNumber = 5;
-  inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
-  inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
-  inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+  const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+  ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+  ::google::protobuf::EnumDescriptorProto* add_enum_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
       enum_type() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
       mutable_enum_type();
 
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
-  inline int service_size() const;
-  inline void clear_service();
+  int service_size() const;
+  void clear_service();
   static const int kServiceFieldNumber = 6;
-  inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
-  inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
-  inline ::google::protobuf::ServiceDescriptorProto* add_service();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+  const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
+  ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
+  ::google::protobuf::ServiceDescriptorProto* add_service();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
       service() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
       mutable_service();
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
-  inline int extension_size() const;
-  inline void clear_extension();
+  int extension_size() const;
+  void clear_extension();
   static const int kExtensionFieldNumber = 7;
-  inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
-  inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
-  inline ::google::protobuf::FieldDescriptorProto* add_extension();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+  const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+  ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+  ::google::protobuf::FieldDescriptorProto* add_extension();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
       extension() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
       mutable_extension();
 
   // optional .google.protobuf.FileOptions options = 8;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 8;
-  inline const ::google::protobuf::FileOptions& options() const;
-  inline ::google::protobuf::FileOptions* mutable_options();
-  inline ::google::protobuf::FileOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::FileOptions* options);
+  const ::google::protobuf::FileOptions& options() const;
+  ::google::protobuf::FileOptions* mutable_options();
+  ::google::protobuf::FileOptions* release_options();
+  void set_allocated_options(::google::protobuf::FileOptions* options);
 
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
-  inline bool has_source_code_info() const;
-  inline void clear_source_code_info();
+  bool has_source_code_info() const;
+  void clear_source_code_info();
   static const int kSourceCodeInfoFieldNumber = 9;
-  inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
-  inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
-  inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
-  inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+  const ::google::protobuf::SourceCodeInfo& source_code_info() const;
+  ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
+  ::google::protobuf::SourceCodeInfo* release_source_code_info();
+  void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
 
   // optional string syntax = 12;
-  inline bool has_syntax() const;
-  inline void clear_syntax();
+  bool has_syntax() const;
+  void clear_syntax();
   static const int kSyntaxFieldNumber = 12;
-  inline const ::std::string& syntax() const;
-  inline void set_syntax(const ::std::string& value);
-  inline void set_syntax(const char* value);
-  inline void set_syntax(const char* value, size_t size);
-  inline ::std::string* mutable_syntax();
-  inline ::std::string* release_syntax();
-  inline void set_allocated_syntax(::std::string* syntax);
+  const ::std::string& syntax() const;
+  void set_syntax(const ::std::string& value);
+  void set_syntax(const char* value);
+  void set_syntax(const char* value, size_t size);
+  ::std::string* mutable_syntax();
+  ::std::string* release_syntax();
+  void set_allocated_syntax(::std::string* syntax);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
  private:
@@ -557,18 +557,18 @@
   // accessors -------------------------------------------------------
 
   // optional int32 start = 1;
-  inline bool has_start() const;
-  inline void clear_start();
+  bool has_start() const;
+  void clear_start();
   static const int kStartFieldNumber = 1;
-  inline ::google::protobuf::int32 start() const;
-  inline void set_start(::google::protobuf::int32 value);
+  ::google::protobuf::int32 start() const;
+  void set_start(::google::protobuf::int32 value);
 
   // optional int32 end = 2;
-  inline bool has_end() const;
-  inline void clear_end();
+  bool has_end() const;
+  void clear_end();
   static const int kEndFieldNumber = 2;
-  inline ::google::protobuf::int32 end() const;
-  inline void set_end(::google::protobuf::int32 value);
+  ::google::protobuf::int32 end() const;
+  void set_end(::google::protobuf::int32 value);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
  private:
@@ -658,97 +658,97 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
-  inline int field_size() const;
-  inline void clear_field();
+  int field_size() const;
+  void clear_field();
   static const int kFieldFieldNumber = 2;
-  inline const ::google::protobuf::FieldDescriptorProto& field(int index) const;
-  inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
-  inline ::google::protobuf::FieldDescriptorProto* add_field();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+  const ::google::protobuf::FieldDescriptorProto& field(int index) const;
+  ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
+  ::google::protobuf::FieldDescriptorProto* add_field();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
       field() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
       mutable_field();
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
-  inline int extension_size() const;
-  inline void clear_extension();
+  int extension_size() const;
+  void clear_extension();
   static const int kExtensionFieldNumber = 6;
-  inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
-  inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
-  inline ::google::protobuf::FieldDescriptorProto* add_extension();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+  const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+  ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+  ::google::protobuf::FieldDescriptorProto* add_extension();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
       extension() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
       mutable_extension();
 
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
-  inline int nested_type_size() const;
-  inline void clear_nested_type();
+  int nested_type_size() const;
+  void clear_nested_type();
   static const int kNestedTypeFieldNumber = 3;
-  inline const ::google::protobuf::DescriptorProto& nested_type(int index) const;
-  inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
-  inline ::google::protobuf::DescriptorProto* add_nested_type();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+  const ::google::protobuf::DescriptorProto& nested_type(int index) const;
+  ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
+  ::google::protobuf::DescriptorProto* add_nested_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
       nested_type() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
       mutable_nested_type();
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
-  inline int enum_type_size() const;
-  inline void clear_enum_type();
+  int enum_type_size() const;
+  void clear_enum_type();
   static const int kEnumTypeFieldNumber = 4;
-  inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
-  inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
-  inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+  const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+  ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+  ::google::protobuf::EnumDescriptorProto* add_enum_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
       enum_type() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
       mutable_enum_type();
 
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
-  inline int extension_range_size() const;
-  inline void clear_extension_range();
+  int extension_range_size() const;
+  void clear_extension_range();
   static const int kExtensionRangeFieldNumber = 5;
-  inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
-  inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
-  inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+  const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
+  ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
+  ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
       extension_range() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
       mutable_extension_range();
 
   // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
-  inline int oneof_decl_size() const;
-  inline void clear_oneof_decl();
+  int oneof_decl_size() const;
+  void clear_oneof_decl();
   static const int kOneofDeclFieldNumber = 8;
-  inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
-  inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
-  inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+  const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
+  ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
+  ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
       oneof_decl() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
       mutable_oneof_decl();
 
   // optional .google.protobuf.MessageOptions options = 7;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 7;
-  inline const ::google::protobuf::MessageOptions& options() const;
-  inline ::google::protobuf::MessageOptions* mutable_options();
-  inline ::google::protobuf::MessageOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::MessageOptions* options);
+  const ::google::protobuf::MessageOptions& options() const;
+  ::google::protobuf::MessageOptions* mutable_options();
+  ::google::protobuf::MessageOptions* release_options();
+  void set_allocated_options(::google::protobuf::MessageOptions* options);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
  private:
@@ -907,89 +907,89 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // optional int32 number = 3;
-  inline bool has_number() const;
-  inline void clear_number();
+  bool has_number() const;
+  void clear_number();
   static const int kNumberFieldNumber = 3;
-  inline ::google::protobuf::int32 number() const;
-  inline void set_number(::google::protobuf::int32 value);
+  ::google::protobuf::int32 number() const;
+  void set_number(::google::protobuf::int32 value);
 
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-  inline bool has_label() const;
-  inline void clear_label();
+  bool has_label() const;
+  void clear_label();
   static const int kLabelFieldNumber = 4;
-  inline ::google::protobuf::FieldDescriptorProto_Label label() const;
-  inline void set_label(::google::protobuf::FieldDescriptorProto_Label value);
+  ::google::protobuf::FieldDescriptorProto_Label label() const;
+  void set_label(::google::protobuf::FieldDescriptorProto_Label value);
 
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-  inline bool has_type() const;
-  inline void clear_type();
+  bool has_type() const;
+  void clear_type();
   static const int kTypeFieldNumber = 5;
-  inline ::google::protobuf::FieldDescriptorProto_Type type() const;
-  inline void set_type(::google::protobuf::FieldDescriptorProto_Type value);
+  ::google::protobuf::FieldDescriptorProto_Type type() const;
+  void set_type(::google::protobuf::FieldDescriptorProto_Type value);
 
   // optional string type_name = 6;
-  inline bool has_type_name() const;
-  inline void clear_type_name();
+  bool has_type_name() const;
+  void clear_type_name();
   static const int kTypeNameFieldNumber = 6;
-  inline const ::std::string& type_name() const;
-  inline void set_type_name(const ::std::string& value);
-  inline void set_type_name(const char* value);
-  inline void set_type_name(const char* value, size_t size);
-  inline ::std::string* mutable_type_name();
-  inline ::std::string* release_type_name();
-  inline void set_allocated_type_name(::std::string* type_name);
+  const ::std::string& type_name() const;
+  void set_type_name(const ::std::string& value);
+  void set_type_name(const char* value);
+  void set_type_name(const char* value, size_t size);
+  ::std::string* mutable_type_name();
+  ::std::string* release_type_name();
+  void set_allocated_type_name(::std::string* type_name);
 
   // optional string extendee = 2;
-  inline bool has_extendee() const;
-  inline void clear_extendee();
+  bool has_extendee() const;
+  void clear_extendee();
   static const int kExtendeeFieldNumber = 2;
-  inline const ::std::string& extendee() const;
-  inline void set_extendee(const ::std::string& value);
-  inline void set_extendee(const char* value);
-  inline void set_extendee(const char* value, size_t size);
-  inline ::std::string* mutable_extendee();
-  inline ::std::string* release_extendee();
-  inline void set_allocated_extendee(::std::string* extendee);
+  const ::std::string& extendee() const;
+  void set_extendee(const ::std::string& value);
+  void set_extendee(const char* value);
+  void set_extendee(const char* value, size_t size);
+  ::std::string* mutable_extendee();
+  ::std::string* release_extendee();
+  void set_allocated_extendee(::std::string* extendee);
 
   // optional string default_value = 7;
-  inline bool has_default_value() const;
-  inline void clear_default_value();
+  bool has_default_value() const;
+  void clear_default_value();
   static const int kDefaultValueFieldNumber = 7;
-  inline const ::std::string& default_value() const;
-  inline void set_default_value(const ::std::string& value);
-  inline void set_default_value(const char* value);
-  inline void set_default_value(const char* value, size_t size);
-  inline ::std::string* mutable_default_value();
-  inline ::std::string* release_default_value();
-  inline void set_allocated_default_value(::std::string* default_value);
+  const ::std::string& default_value() const;
+  void set_default_value(const ::std::string& value);
+  void set_default_value(const char* value);
+  void set_default_value(const char* value, size_t size);
+  ::std::string* mutable_default_value();
+  ::std::string* release_default_value();
+  void set_allocated_default_value(::std::string* default_value);
 
   // optional int32 oneof_index = 9;
-  inline bool has_oneof_index() const;
-  inline void clear_oneof_index();
+  bool has_oneof_index() const;
+  void clear_oneof_index();
   static const int kOneofIndexFieldNumber = 9;
-  inline ::google::protobuf::int32 oneof_index() const;
-  inline void set_oneof_index(::google::protobuf::int32 value);
+  ::google::protobuf::int32 oneof_index() const;
+  void set_oneof_index(::google::protobuf::int32 value);
 
   // optional .google.protobuf.FieldOptions options = 8;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 8;
-  inline const ::google::protobuf::FieldOptions& options() const;
-  inline ::google::protobuf::FieldOptions* mutable_options();
-  inline ::google::protobuf::FieldOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::FieldOptions* options);
+  const ::google::protobuf::FieldOptions& options() const;
+  ::google::protobuf::FieldOptions* mutable_options();
+  ::google::protobuf::FieldOptions* release_options();
+  void set_allocated_options(::google::protobuf::FieldOptions* options);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
  private:
@@ -1098,16 +1098,16 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto)
  private:
@@ -1192,37 +1192,37 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
-  inline int value_size() const;
-  inline void clear_value();
+  int value_size() const;
+  void clear_value();
   static const int kValueFieldNumber = 2;
-  inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
-  inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
-  inline ::google::protobuf::EnumValueDescriptorProto* add_value();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+  const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
+  ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
+  ::google::protobuf::EnumValueDescriptorProto* add_value();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
       value() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
       mutable_value();
 
   // optional .google.protobuf.EnumOptions options = 3;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 3;
-  inline const ::google::protobuf::EnumOptions& options() const;
-  inline ::google::protobuf::EnumOptions* mutable_options();
-  inline ::google::protobuf::EnumOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::EnumOptions* options);
+  const ::google::protobuf::EnumOptions& options() const;
+  ::google::protobuf::EnumOptions* mutable_options();
+  ::google::protobuf::EnumOptions* release_options();
+  void set_allocated_options(::google::protobuf::EnumOptions* options);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
  private:
@@ -1311,32 +1311,32 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // optional int32 number = 2;
-  inline bool has_number() const;
-  inline void clear_number();
+  bool has_number() const;
+  void clear_number();
   static const int kNumberFieldNumber = 2;
-  inline ::google::protobuf::int32 number() const;
-  inline void set_number(::google::protobuf::int32 value);
+  ::google::protobuf::int32 number() const;
+  void set_number(::google::protobuf::int32 value);
 
   // optional .google.protobuf.EnumValueOptions options = 3;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 3;
-  inline const ::google::protobuf::EnumValueOptions& options() const;
-  inline ::google::protobuf::EnumValueOptions* mutable_options();
-  inline ::google::protobuf::EnumValueOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+  const ::google::protobuf::EnumValueOptions& options() const;
+  ::google::protobuf::EnumValueOptions* mutable_options();
+  ::google::protobuf::EnumValueOptions* release_options();
+  void set_allocated_options(::google::protobuf::EnumValueOptions* options);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
  private:
@@ -1427,37 +1427,37 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
-  inline int method_size() const;
-  inline void clear_method();
+  int method_size() const;
+  void clear_method();
   static const int kMethodFieldNumber = 2;
-  inline const ::google::protobuf::MethodDescriptorProto& method(int index) const;
-  inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
-  inline ::google::protobuf::MethodDescriptorProto* add_method();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+  const ::google::protobuf::MethodDescriptorProto& method(int index) const;
+  ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
+  ::google::protobuf::MethodDescriptorProto* add_method();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
       method() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
       mutable_method();
 
   // optional .google.protobuf.ServiceOptions options = 3;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 3;
-  inline const ::google::protobuf::ServiceOptions& options() const;
-  inline ::google::protobuf::ServiceOptions* mutable_options();
-  inline ::google::protobuf::ServiceOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::ServiceOptions* options);
+  const ::google::protobuf::ServiceOptions& options() const;
+  ::google::protobuf::ServiceOptions* mutable_options();
+  ::google::protobuf::ServiceOptions* release_options();
+  void set_allocated_options(::google::protobuf::ServiceOptions* options);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
  private:
@@ -1546,63 +1546,63 @@
   // accessors -------------------------------------------------------
 
   // optional string name = 1;
-  inline bool has_name() const;
-  inline void clear_name();
+  bool has_name() const;
+  void clear_name();
   static const int kNameFieldNumber = 1;
-  inline const ::std::string& name() const;
-  inline void set_name(const ::std::string& value);
-  inline void set_name(const char* value);
-  inline void set_name(const char* value, size_t size);
-  inline ::std::string* mutable_name();
-  inline ::std::string* release_name();
-  inline void set_allocated_name(::std::string* name);
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
 
   // optional string input_type = 2;
-  inline bool has_input_type() const;
-  inline void clear_input_type();
+  bool has_input_type() const;
+  void clear_input_type();
   static const int kInputTypeFieldNumber = 2;
-  inline const ::std::string& input_type() const;
-  inline void set_input_type(const ::std::string& value);
-  inline void set_input_type(const char* value);
-  inline void set_input_type(const char* value, size_t size);
-  inline ::std::string* mutable_input_type();
-  inline ::std::string* release_input_type();
-  inline void set_allocated_input_type(::std::string* input_type);
+  const ::std::string& input_type() const;
+  void set_input_type(const ::std::string& value);
+  void set_input_type(const char* value);
+  void set_input_type(const char* value, size_t size);
+  ::std::string* mutable_input_type();
+  ::std::string* release_input_type();
+  void set_allocated_input_type(::std::string* input_type);
 
   // optional string output_type = 3;
-  inline bool has_output_type() const;
-  inline void clear_output_type();
+  bool has_output_type() const;
+  void clear_output_type();
   static const int kOutputTypeFieldNumber = 3;
-  inline const ::std::string& output_type() const;
-  inline void set_output_type(const ::std::string& value);
-  inline void set_output_type(const char* value);
-  inline void set_output_type(const char* value, size_t size);
-  inline ::std::string* mutable_output_type();
-  inline ::std::string* release_output_type();
-  inline void set_allocated_output_type(::std::string* output_type);
+  const ::std::string& output_type() const;
+  void set_output_type(const ::std::string& value);
+  void set_output_type(const char* value);
+  void set_output_type(const char* value, size_t size);
+  ::std::string* mutable_output_type();
+  ::std::string* release_output_type();
+  void set_allocated_output_type(::std::string* output_type);
 
   // optional .google.protobuf.MethodOptions options = 4;
-  inline bool has_options() const;
-  inline void clear_options();
+  bool has_options() const;
+  void clear_options();
   static const int kOptionsFieldNumber = 4;
-  inline const ::google::protobuf::MethodOptions& options() const;
-  inline ::google::protobuf::MethodOptions* mutable_options();
-  inline ::google::protobuf::MethodOptions* release_options();
-  inline void set_allocated_options(::google::protobuf::MethodOptions* options);
+  const ::google::protobuf::MethodOptions& options() const;
+  ::google::protobuf::MethodOptions* mutable_options();
+  ::google::protobuf::MethodOptions* release_options();
+  void set_allocated_options(::google::protobuf::MethodOptions* options);
 
   // optional bool client_streaming = 5 [default = false];
-  inline bool has_client_streaming() const;
-  inline void clear_client_streaming();
+  bool has_client_streaming() const;
+  void clear_client_streaming();
   static const int kClientStreamingFieldNumber = 5;
-  inline bool client_streaming() const;
-  inline void set_client_streaming(bool value);
+  bool client_streaming() const;
+  void set_client_streaming(bool value);
 
   // optional bool server_streaming = 6 [default = false];
-  inline bool has_server_streaming() const;
-  inline void clear_server_streaming();
+  bool has_server_streaming() const;
+  void clear_server_streaming();
   static const int kServerStreamingFieldNumber = 6;
-  inline bool server_streaming() const;
-  inline void set_server_streaming(bool value);
+  bool server_streaming() const;
+  void set_server_streaming(bool value);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
  private:
@@ -1727,114 +1727,126 @@
   // accessors -------------------------------------------------------
 
   // optional string java_package = 1;
-  inline bool has_java_package() const;
-  inline void clear_java_package();
+  bool has_java_package() const;
+  void clear_java_package();
   static const int kJavaPackageFieldNumber = 1;
-  inline const ::std::string& java_package() const;
-  inline void set_java_package(const ::std::string& value);
-  inline void set_java_package(const char* value);
-  inline void set_java_package(const char* value, size_t size);
-  inline ::std::string* mutable_java_package();
-  inline ::std::string* release_java_package();
-  inline void set_allocated_java_package(::std::string* java_package);
+  const ::std::string& java_package() const;
+  void set_java_package(const ::std::string& value);
+  void set_java_package(const char* value);
+  void set_java_package(const char* value, size_t size);
+  ::std::string* mutable_java_package();
+  ::std::string* release_java_package();
+  void set_allocated_java_package(::std::string* java_package);
 
   // optional string java_outer_classname = 8;
-  inline bool has_java_outer_classname() const;
-  inline void clear_java_outer_classname();
+  bool has_java_outer_classname() const;
+  void clear_java_outer_classname();
   static const int kJavaOuterClassnameFieldNumber = 8;
-  inline const ::std::string& java_outer_classname() const;
-  inline void set_java_outer_classname(const ::std::string& value);
-  inline void set_java_outer_classname(const char* value);
-  inline void set_java_outer_classname(const char* value, size_t size);
-  inline ::std::string* mutable_java_outer_classname();
-  inline ::std::string* release_java_outer_classname();
-  inline void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+  const ::std::string& java_outer_classname() const;
+  void set_java_outer_classname(const ::std::string& value);
+  void set_java_outer_classname(const char* value);
+  void set_java_outer_classname(const char* value, size_t size);
+  ::std::string* mutable_java_outer_classname();
+  ::std::string* release_java_outer_classname();
+  void set_allocated_java_outer_classname(::std::string* java_outer_classname);
 
   // optional bool java_multiple_files = 10 [default = false];
-  inline bool has_java_multiple_files() const;
-  inline void clear_java_multiple_files();
+  bool has_java_multiple_files() const;
+  void clear_java_multiple_files();
   static const int kJavaMultipleFilesFieldNumber = 10;
-  inline bool java_multiple_files() const;
-  inline void set_java_multiple_files(bool value);
+  bool java_multiple_files() const;
+  void set_java_multiple_files(bool value);
 
   // optional bool java_generate_equals_and_hash = 20 [default = false];
-  inline bool has_java_generate_equals_and_hash() const;
-  inline void clear_java_generate_equals_and_hash();
+  bool has_java_generate_equals_and_hash() const;
+  void clear_java_generate_equals_and_hash();
   static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
-  inline bool java_generate_equals_and_hash() const;
-  inline void set_java_generate_equals_and_hash(bool value);
+  bool java_generate_equals_and_hash() const;
+  void set_java_generate_equals_and_hash(bool value);
 
   // optional bool java_string_check_utf8 = 27 [default = false];
-  inline bool has_java_string_check_utf8() const;
-  inline void clear_java_string_check_utf8();
+  bool has_java_string_check_utf8() const;
+  void clear_java_string_check_utf8();
   static const int kJavaStringCheckUtf8FieldNumber = 27;
-  inline bool java_string_check_utf8() const;
-  inline void set_java_string_check_utf8(bool value);
+  bool java_string_check_utf8() const;
+  void set_java_string_check_utf8(bool value);
 
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  inline bool has_optimize_for() const;
-  inline void clear_optimize_for();
+  bool has_optimize_for() const;
+  void clear_optimize_for();
   static const int kOptimizeForFieldNumber = 9;
-  inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
-  inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
+  ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
+  void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
 
   // optional string go_package = 11;
-  inline bool has_go_package() const;
-  inline void clear_go_package();
+  bool has_go_package() const;
+  void clear_go_package();
   static const int kGoPackageFieldNumber = 11;
-  inline const ::std::string& go_package() const;
-  inline void set_go_package(const ::std::string& value);
-  inline void set_go_package(const char* value);
-  inline void set_go_package(const char* value, size_t size);
-  inline ::std::string* mutable_go_package();
-  inline ::std::string* release_go_package();
-  inline void set_allocated_go_package(::std::string* go_package);
+  const ::std::string& go_package() const;
+  void set_go_package(const ::std::string& value);
+  void set_go_package(const char* value);
+  void set_go_package(const char* value, size_t size);
+  ::std::string* mutable_go_package();
+  ::std::string* release_go_package();
+  void set_allocated_go_package(::std::string* go_package);
 
   // optional bool cc_generic_services = 16 [default = false];
-  inline bool has_cc_generic_services() const;
-  inline void clear_cc_generic_services();
+  bool has_cc_generic_services() const;
+  void clear_cc_generic_services();
   static const int kCcGenericServicesFieldNumber = 16;
-  inline bool cc_generic_services() const;
-  inline void set_cc_generic_services(bool value);
+  bool cc_generic_services() const;
+  void set_cc_generic_services(bool value);
 
   // optional bool java_generic_services = 17 [default = false];
-  inline bool has_java_generic_services() const;
-  inline void clear_java_generic_services();
+  bool has_java_generic_services() const;
+  void clear_java_generic_services();
   static const int kJavaGenericServicesFieldNumber = 17;
-  inline bool java_generic_services() const;
-  inline void set_java_generic_services(bool value);
+  bool java_generic_services() const;
+  void set_java_generic_services(bool value);
 
   // optional bool py_generic_services = 18 [default = false];
-  inline bool has_py_generic_services() const;
-  inline void clear_py_generic_services();
+  bool has_py_generic_services() const;
+  void clear_py_generic_services();
   static const int kPyGenericServicesFieldNumber = 18;
-  inline bool py_generic_services() const;
-  inline void set_py_generic_services(bool value);
+  bool py_generic_services() const;
+  void set_py_generic_services(bool value);
 
   // optional bool deprecated = 23 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 23;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // optional bool cc_enable_arenas = 31 [default = false];
-  inline bool has_cc_enable_arenas() const;
-  inline void clear_cc_enable_arenas();
+  bool has_cc_enable_arenas() const;
+  void clear_cc_enable_arenas();
   static const int kCcEnableArenasFieldNumber = 31;
-  inline bool cc_enable_arenas() const;
-  inline void set_cc_enable_arenas(bool value);
+  bool cc_enable_arenas() const;
+  void set_cc_enable_arenas(bool value);
+
+  // optional string objc_class_prefix = 36;
+  bool has_objc_class_prefix() const;
+  void clear_objc_class_prefix();
+  static const int kObjcClassPrefixFieldNumber = 36;
+  const ::std::string& objc_class_prefix() const;
+  void set_objc_class_prefix(const ::std::string& value);
+  void set_objc_class_prefix(const char* value);
+  void set_objc_class_prefix(const char* value, size_t size);
+  ::std::string* mutable_objc_class_prefix();
+  ::std::string* release_objc_class_prefix();
+  void set_allocated_objc_class_prefix(::std::string* objc_class_prefix);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
@@ -1864,6 +1876,8 @@
   inline void clear_has_deprecated();
   inline void set_has_cc_enable_arenas();
   inline void clear_has_cc_enable_arenas();
+  inline void set_has_objc_class_prefix();
+  inline void clear_has_objc_class_prefix();
 
   ::google::protobuf::internal::ExtensionSet _extensions_;
 
@@ -1878,6 +1892,7 @@
   bool cc_generic_services_;
   int optimize_for_;
   ::google::protobuf::internal::ArenaStringPtr go_package_;
+  ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   bool java_generic_services_;
   bool py_generic_services_;
@@ -1957,43 +1972,43 @@
   // accessors -------------------------------------------------------
 
   // optional bool message_set_wire_format = 1 [default = false];
-  inline bool has_message_set_wire_format() const;
-  inline void clear_message_set_wire_format();
+  bool has_message_set_wire_format() const;
+  void clear_message_set_wire_format();
   static const int kMessageSetWireFormatFieldNumber = 1;
-  inline bool message_set_wire_format() const;
-  inline void set_message_set_wire_format(bool value);
+  bool message_set_wire_format() const;
+  void set_message_set_wire_format(bool value);
 
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
-  inline bool has_no_standard_descriptor_accessor() const;
-  inline void clear_no_standard_descriptor_accessor();
+  bool has_no_standard_descriptor_accessor() const;
+  void clear_no_standard_descriptor_accessor();
   static const int kNoStandardDescriptorAccessorFieldNumber = 2;
-  inline bool no_standard_descriptor_accessor() const;
-  inline void set_no_standard_descriptor_accessor(bool value);
+  bool no_standard_descriptor_accessor() const;
+  void set_no_standard_descriptor_accessor(bool value);
 
   // optional bool deprecated = 3 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 3;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // optional bool map_entry = 7;
-  inline bool has_map_entry() const;
-  inline void clear_map_entry();
+  bool has_map_entry() const;
+  void clear_map_entry();
   static const int kMapEntryFieldNumber = 7;
-  inline bool map_entry() const;
-  inline void set_map_entry(bool value);
+  bool map_entry() const;
+  void set_map_entry(bool value);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
@@ -2117,50 +2132,50 @@
   // accessors -------------------------------------------------------
 
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-  inline bool has_ctype() const;
-  inline void clear_ctype();
+  bool has_ctype() const;
+  void clear_ctype();
   static const int kCtypeFieldNumber = 1;
-  inline ::google::protobuf::FieldOptions_CType ctype() const;
-  inline void set_ctype(::google::protobuf::FieldOptions_CType value);
+  ::google::protobuf::FieldOptions_CType ctype() const;
+  void set_ctype(::google::protobuf::FieldOptions_CType value);
 
   // optional bool packed = 2;
-  inline bool has_packed() const;
-  inline void clear_packed();
+  bool has_packed() const;
+  void clear_packed();
   static const int kPackedFieldNumber = 2;
-  inline bool packed() const;
-  inline void set_packed(bool value);
+  bool packed() const;
+  void set_packed(bool value);
 
   // optional bool lazy = 5 [default = false];
-  inline bool has_lazy() const;
-  inline void clear_lazy();
+  bool has_lazy() const;
+  void clear_lazy();
   static const int kLazyFieldNumber = 5;
-  inline bool lazy() const;
-  inline void set_lazy(bool value);
+  bool lazy() const;
+  void set_lazy(bool value);
 
   // optional bool deprecated = 3 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 3;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // optional bool weak = 10 [default = false];
-  inline bool has_weak() const;
-  inline void clear_weak();
+  bool has_weak() const;
+  void clear_weak();
   static const int kWeakFieldNumber = 10;
-  inline bool weak() const;
-  inline void set_weak(bool value);
+  bool weak() const;
+  void set_weak(bool value);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
@@ -2262,29 +2277,29 @@
   // accessors -------------------------------------------------------
 
   // optional bool allow_alias = 2;
-  inline bool has_allow_alias() const;
-  inline void clear_allow_alias();
+  bool has_allow_alias() const;
+  void clear_allow_alias();
   static const int kAllowAliasFieldNumber = 2;
-  inline bool allow_alias() const;
-  inline void set_allow_alias(bool value);
+  bool allow_alias() const;
+  void set_allow_alias(bool value);
 
   // optional bool deprecated = 3 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 3;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
@@ -2377,22 +2392,22 @@
   // accessors -------------------------------------------------------
 
   // optional bool deprecated = 1 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 1;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
@@ -2482,22 +2497,22 @@
   // accessors -------------------------------------------------------
 
   // optional bool deprecated = 33 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 33;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
@@ -2587,22 +2602,22 @@
   // accessors -------------------------------------------------------
 
   // optional bool deprecated = 33 [default = false];
-  inline bool has_deprecated() const;
-  inline void clear_deprecated();
+  bool has_deprecated() const;
+  void clear_deprecated();
   static const int kDeprecatedFieldNumber = 33;
-  inline bool deprecated() const;
-  inline void set_deprecated(bool value);
+  bool deprecated() const;
+  void set_deprecated(bool value);
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  inline int uninterpreted_option_size() const;
-  inline void clear_uninterpreted_option();
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
   static const int kUninterpretedOptionFieldNumber = 999;
-  inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
-  inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
-  inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
       uninterpreted_option() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
 
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
@@ -2692,23 +2707,23 @@
   // accessors -------------------------------------------------------
 
   // required string name_part = 1;
-  inline bool has_name_part() const;
-  inline void clear_name_part();
+  bool has_name_part() const;
+  void clear_name_part();
   static const int kNamePartFieldNumber = 1;
-  inline const ::std::string& name_part() const;
-  inline void set_name_part(const ::std::string& value);
-  inline void set_name_part(const char* value);
-  inline void set_name_part(const char* value, size_t size);
-  inline ::std::string* mutable_name_part();
-  inline ::std::string* release_name_part();
-  inline void set_allocated_name_part(::std::string* name_part);
+  const ::std::string& name_part() const;
+  void set_name_part(const ::std::string& value);
+  void set_name_part(const char* value);
+  void set_name_part(const char* value, size_t size);
+  ::std::string* mutable_name_part();
+  ::std::string* release_name_part();
+  void set_allocated_name_part(::std::string* name_part);
 
   // required bool is_extension = 2;
-  inline bool has_is_extension() const;
-  inline void clear_is_extension();
+  bool has_is_extension() const;
+  void clear_is_extension();
   static const int kIsExtensionFieldNumber = 2;
-  inline bool is_extension() const;
-  inline void set_is_extension(bool value);
+  bool is_extension() const;
+  void set_is_extension(bool value);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
  private:
@@ -2801,73 +2816,73 @@
   // accessors -------------------------------------------------------
 
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
-  inline int name_size() const;
-  inline void clear_name();
+  int name_size() const;
+  void clear_name();
   static const int kNameFieldNumber = 2;
-  inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
-  inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
-  inline ::google::protobuf::UninterpretedOption_NamePart* add_name();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+  const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
+  ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
+  ::google::protobuf::UninterpretedOption_NamePart* add_name();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
       name() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
       mutable_name();
 
   // optional string identifier_value = 3;
-  inline bool has_identifier_value() const;
-  inline void clear_identifier_value();
+  bool has_identifier_value() const;
+  void clear_identifier_value();
   static const int kIdentifierValueFieldNumber = 3;
-  inline const ::std::string& identifier_value() const;
-  inline void set_identifier_value(const ::std::string& value);
-  inline void set_identifier_value(const char* value);
-  inline void set_identifier_value(const char* value, size_t size);
-  inline ::std::string* mutable_identifier_value();
-  inline ::std::string* release_identifier_value();
-  inline void set_allocated_identifier_value(::std::string* identifier_value);
+  const ::std::string& identifier_value() const;
+  void set_identifier_value(const ::std::string& value);
+  void set_identifier_value(const char* value);
+  void set_identifier_value(const char* value, size_t size);
+  ::std::string* mutable_identifier_value();
+  ::std::string* release_identifier_value();
+  void set_allocated_identifier_value(::std::string* identifier_value);
 
   // optional uint64 positive_int_value = 4;
-  inline bool has_positive_int_value() const;
-  inline void clear_positive_int_value();
+  bool has_positive_int_value() const;
+  void clear_positive_int_value();
   static const int kPositiveIntValueFieldNumber = 4;
-  inline ::google::protobuf::uint64 positive_int_value() const;
-  inline void set_positive_int_value(::google::protobuf::uint64 value);
+  ::google::protobuf::uint64 positive_int_value() const;
+  void set_positive_int_value(::google::protobuf::uint64 value);
 
   // optional int64 negative_int_value = 5;
-  inline bool has_negative_int_value() const;
-  inline void clear_negative_int_value();
+  bool has_negative_int_value() const;
+  void clear_negative_int_value();
   static const int kNegativeIntValueFieldNumber = 5;
-  inline ::google::protobuf::int64 negative_int_value() const;
-  inline void set_negative_int_value(::google::protobuf::int64 value);
+  ::google::protobuf::int64 negative_int_value() const;
+  void set_negative_int_value(::google::protobuf::int64 value);
 
   // optional double double_value = 6;
-  inline bool has_double_value() const;
-  inline void clear_double_value();
+  bool has_double_value() const;
+  void clear_double_value();
   static const int kDoubleValueFieldNumber = 6;
-  inline double double_value() const;
-  inline void set_double_value(double value);
+  double double_value() const;
+  void set_double_value(double value);
 
   // optional bytes string_value = 7;
-  inline bool has_string_value() const;
-  inline void clear_string_value();
+  bool has_string_value() const;
+  void clear_string_value();
   static const int kStringValueFieldNumber = 7;
-  inline const ::std::string& string_value() const;
-  inline void set_string_value(const ::std::string& value);
-  inline void set_string_value(const char* value);
-  inline void set_string_value(const void* value, size_t size);
-  inline ::std::string* mutable_string_value();
-  inline ::std::string* release_string_value();
-  inline void set_allocated_string_value(::std::string* string_value);
+  const ::std::string& string_value() const;
+  void set_string_value(const ::std::string& value);
+  void set_string_value(const char* value);
+  void set_string_value(const void* value, size_t size);
+  ::std::string* mutable_string_value();
+  ::std::string* release_string_value();
+  void set_allocated_string_value(::std::string* string_value);
 
   // optional string aggregate_value = 8;
-  inline bool has_aggregate_value() const;
-  inline void clear_aggregate_value();
+  bool has_aggregate_value() const;
+  void clear_aggregate_value();
   static const int kAggregateValueFieldNumber = 8;
-  inline const ::std::string& aggregate_value() const;
-  inline void set_aggregate_value(const ::std::string& value);
-  inline void set_aggregate_value(const char* value);
-  inline void set_aggregate_value(const char* value, size_t size);
-  inline ::std::string* mutable_aggregate_value();
-  inline ::std::string* release_aggregate_value();
-  inline void set_allocated_aggregate_value(::std::string* aggregate_value);
+  const ::std::string& aggregate_value() const;
+  void set_aggregate_value(const ::std::string& value);
+  void set_aggregate_value(const char* value);
+  void set_aggregate_value(const char* value, size_t size);
+  ::std::string* mutable_aggregate_value();
+  ::std::string* release_aggregate_value();
+  void set_allocated_aggregate_value(::std::string* aggregate_value);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
  private:
@@ -2968,52 +2983,68 @@
   // accessors -------------------------------------------------------
 
   // repeated int32 path = 1 [packed = true];
-  inline int path_size() const;
-  inline void clear_path();
+  int path_size() const;
+  void clear_path();
   static const int kPathFieldNumber = 1;
-  inline ::google::protobuf::int32 path(int index) const;
-  inline void set_path(int index, ::google::protobuf::int32 value);
-  inline void add_path(::google::protobuf::int32 value);
-  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+  ::google::protobuf::int32 path(int index) const;
+  void set_path(int index, ::google::protobuf::int32 value);
+  void add_path(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
       path() const;
-  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
       mutable_path();
 
   // repeated int32 span = 2 [packed = true];
-  inline int span_size() const;
-  inline void clear_span();
+  int span_size() const;
+  void clear_span();
   static const int kSpanFieldNumber = 2;
-  inline ::google::protobuf::int32 span(int index) const;
-  inline void set_span(int index, ::google::protobuf::int32 value);
-  inline void add_span(::google::protobuf::int32 value);
-  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+  ::google::protobuf::int32 span(int index) const;
+  void set_span(int index, ::google::protobuf::int32 value);
+  void add_span(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
       span() const;
-  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
       mutable_span();
 
   // optional string leading_comments = 3;
-  inline bool has_leading_comments() const;
-  inline void clear_leading_comments();
+  bool has_leading_comments() const;
+  void clear_leading_comments();
   static const int kLeadingCommentsFieldNumber = 3;
-  inline const ::std::string& leading_comments() const;
-  inline void set_leading_comments(const ::std::string& value);
-  inline void set_leading_comments(const char* value);
-  inline void set_leading_comments(const char* value, size_t size);
-  inline ::std::string* mutable_leading_comments();
-  inline ::std::string* release_leading_comments();
-  inline void set_allocated_leading_comments(::std::string* leading_comments);
+  const ::std::string& leading_comments() const;
+  void set_leading_comments(const ::std::string& value);
+  void set_leading_comments(const char* value);
+  void set_leading_comments(const char* value, size_t size);
+  ::std::string* mutable_leading_comments();
+  ::std::string* release_leading_comments();
+  void set_allocated_leading_comments(::std::string* leading_comments);
 
   // optional string trailing_comments = 4;
-  inline bool has_trailing_comments() const;
-  inline void clear_trailing_comments();
+  bool has_trailing_comments() const;
+  void clear_trailing_comments();
   static const int kTrailingCommentsFieldNumber = 4;
-  inline const ::std::string& trailing_comments() const;
-  inline void set_trailing_comments(const ::std::string& value);
-  inline void set_trailing_comments(const char* value);
-  inline void set_trailing_comments(const char* value, size_t size);
-  inline ::std::string* mutable_trailing_comments();
-  inline ::std::string* release_trailing_comments();
-  inline void set_allocated_trailing_comments(::std::string* trailing_comments);
+  const ::std::string& trailing_comments() const;
+  void set_trailing_comments(const ::std::string& value);
+  void set_trailing_comments(const char* value);
+  void set_trailing_comments(const char* value, size_t size);
+  ::std::string* mutable_trailing_comments();
+  ::std::string* release_trailing_comments();
+  void set_allocated_trailing_comments(::std::string* trailing_comments);
+
+  // repeated string leading_detached_comments = 6;
+  int leading_detached_comments_size() const;
+  void clear_leading_detached_comments();
+  static const int kLeadingDetachedCommentsFieldNumber = 6;
+  const ::std::string& leading_detached_comments(int index) const;
+  ::std::string* mutable_leading_detached_comments(int index);
+  void set_leading_detached_comments(int index, const ::std::string& value);
+  void set_leading_detached_comments(int index, const char* value);
+  void set_leading_detached_comments(int index, const char* value, size_t size);
+  ::std::string* add_leading_detached_comments();
+  void add_leading_detached_comments(const ::std::string& value);
+  void add_leading_detached_comments(const char* value);
+  void add_leading_detached_comments(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments();
 
   // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
  private:
@@ -3031,6 +3062,7 @@
   mutable int _span_cached_byte_size_;
   ::google::protobuf::internal::ArenaStringPtr leading_comments_;
   ::google::protobuf::internal::ArenaStringPtr trailing_comments_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_;
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -3107,15 +3139,15 @@
   // accessors -------------------------------------------------------
 
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
-  inline int location_size() const;
-  inline void clear_location();
+  int location_size() const;
+  void clear_location();
   static const int kLocationFieldNumber = 1;
-  inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
-  inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
-  inline ::google::protobuf::SourceCodeInfo_Location* add_location();
-  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+  const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
+  ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
+  ::google::protobuf::SourceCodeInfo_Location* add_location();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
       location() const;
-  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
       mutable_location();
 
   // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
@@ -3137,6 +3169,7 @@
 
 // ===================================================================
 
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
 // FileDescriptorSet
 
 // repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -5416,6 +5449,59 @@
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
 }
 
+// optional string objc_class_prefix = 36;
+inline bool FileOptions::has_objc_class_prefix() const {
+  return (_has_bits_[0] & 0x00001000u) != 0;
+}
+inline void FileOptions::set_has_objc_class_prefix() {
+  _has_bits_[0] |= 0x00001000u;
+}
+inline void FileOptions::clear_has_objc_class_prefix() {
+  _has_bits_[0] &= ~0x00001000u;
+}
+inline void FileOptions::clear_objc_class_prefix() {
+  objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_objc_class_prefix();
+}
+inline const ::std::string& FileOptions::objc_class_prefix() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline ::std::string* FileOptions::mutable_objc_class_prefix() {
+  set_has_objc_class_prefix();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_objc_class_prefix() {
+  clear_has_objc_class_prefix();
+  return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+  if (objc_class_prefix != NULL) {
+    set_has_objc_class_prefix();
+  } else {
+    clear_has_objc_class_prefix();
+  }
+  objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FileOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
@@ -6503,6 +6589,60 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
 }
 
+// repeated string leading_detached_comments = 6;
+inline int SourceCodeInfo_Location::leading_detached_comments_size() const {
+  return leading_detached_comments_.size();
+}
+inline void SourceCodeInfo_Location::clear_leading_detached_comments() {
+  leading_detached_comments_.Clear();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Get(index);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Mutable(index);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  leading_detached_comments_.Mutable(index)->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+  leading_detached_comments_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+  leading_detached_comments_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+  return leading_detached_comments_.Add();
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+  leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return &leading_detached_comments_;
+}
+
 // -------------------------------------------------------------------
 
 // SourceCodeInfo
@@ -6537,6 +6677,7 @@
   return &location_;
 }
 
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
 
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index e17c0cc..367b16e 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -172,9 +172,7 @@
   optional string default_value = 7;
 
   // If set, gives the index of a oneof in the containing type's oneof_decl
-  // list.  This field is a member of that oneof.  Extensions of a oneof should
-  // not set this since the oneof to which they belong will be inferred based
-  // on the extension range containing the extension's field number.
+  // list.  This field is a member of that oneof.
   optional int32 oneof_index = 9;
 
   optional FieldOptions options = 8;
@@ -344,12 +342,15 @@
   // least, this is a formalization for deprecating files.
   optional bool deprecated = 23 [default=false];
 
-
   // Enables the use of arenas for the proto messages in this file. This applies
   // only to generated classes for C++.
   optional bool cc_enable_arenas = 31 [default=false];
 
 
+  // Sets the objective c class prefix which is prepended to all objective c
+  // generated classes from this .proto. There is no default.
+  optional string objc_class_prefix = 36;
+
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
@@ -681,6 +682,11 @@
     // A series of line comments appearing on consecutive lines, with no other
     // tokens appearing on those lines, will be treated as a single comment.
     //
+    // leading_detached_comments will keep paragraphs of comments that appear
+    // before (but not connected to) the current element. Each paragraph,
+    // separated by empty lines, will be one comment element in the repeated
+    // field.
+    //
     // Only the comment content is provided; comment markers (e.g. //) are
     // stripped out.  For block comments, leading whitespace and an asterisk
     // will be stripped from the beginning of each line other than the first.
@@ -701,6 +707,12 @@
     //   // Another line attached to qux.
     //   optional double qux = 4;
     //
+    //   // Detached comment for corge. This is not leading or trailing comments
+    //   // to qux or corge because there are blank lines separating it from
+    //   // both.
+    //
+    //   // Detached comment for corge paragraph 2.
+    //
     //   optional string corge = 5;
     //   /* Block comment attached
     //    * to corge.  Leading asterisks
@@ -708,7 +720,10 @@
     //   /* Block comment attached to
     //    * grault. */
     //   optional int32 grault = 6;
+    //
+    //   // ignored detached comments.
     optional string leading_comments = 3;
     optional string trailing_comments = 4;
+    repeated string leading_detached_comments = 6;
   }
 }
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index d024eab..2117c02 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -153,10 +153,10 @@
   if (!field.extendee().empty() && field.extendee()[0] == '.') {
     // The extension is fully-qualified.  We can use it as a lookup key in
     // the by_symbol_ table.
-    if (!InsertIfNotPresent(&by_extension_,
-                            make_pair(field.extendee().substr(1),
-                                      field.number()),
-                            value)) {
+    if (!InsertIfNotPresent(
+            &by_extension_,
+            std::make_pair(field.extendee().substr(1), field.number()),
+            value)) {
       GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
                     "extend " << field.extendee() << " { "
                  << field.name() << " = " << field.number() << " }";
@@ -189,17 +189,16 @@
 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
     const string& containing_type,
     int field_number) {
-  return FindWithDefault(by_extension_,
-                         make_pair(containing_type, field_number),
-                         Value());
+  return FindWithDefault(
+      by_extension_, std::make_pair(containing_type, field_number), Value());
 }
 
 template <typename Value>
 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
     const string& containing_type,
     vector<int>* output) {
-  typename map<pair<string, int>, Value >::const_iterator it =
-      by_extension_.lower_bound(make_pair(containing_type, 0));
+  typename map<pair<string, int>, Value>::const_iterator it =
+      by_extension_.lower_bound(std::make_pair(containing_type, 0));
   bool success = false;
 
   for (; it != by_extension_.end() && it->first.first == containing_type;
@@ -310,7 +309,7 @@
     const void* encoded_file_descriptor, int size) {
   FileDescriptorProto file;
   if (file.ParseFromArray(encoded_file_descriptor, size)) {
-    return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
+    return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size));
   } else {
     GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
                   "EncodedDescriptorDatabase::Add().";
@@ -525,15 +524,16 @@
 
   for (int i = 0; i < sources_.size(); i++) {
     if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
-      copy(results.begin(), results.end(),
-           insert_iterator<set<int> >(merged_results, merged_results.begin()));
+      std::copy(
+          results.begin(), results.end(),
+          insert_iterator<set<int> >(merged_results, merged_results.begin()));
       success = true;
     }
     results.clear();
   }
 
-  copy(merged_results.begin(), merged_results.end(),
-       insert_iterator<vector<int> >(*output, output->end()));
+  std::copy(merged_results.begin(), merged_results.end(),
+            insert_iterator<vector<int> >(*output, output->end()));
 
   return success;
 }
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 6642d71..1c03c44 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -408,7 +408,7 @@
     vector<int> numbers;
     EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
     ASSERT_EQ(2, numbers.size());
-    sort(numbers.begin(), numbers.end());
+    std::sort(numbers.begin(), numbers.end());
     EXPECT_EQ(5, numbers[0]);
     EXPECT_EQ(32, numbers[1]);
   }
@@ -722,7 +722,7 @@
     vector<int> numbers;
     EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
     ASSERT_EQ(2, numbers.size());
-    sort(numbers.begin(), numbers.end());
+    std::sort(numbers.begin(), numbers.end());
     EXPECT_EQ(12, numbers[0]);
     EXPECT_EQ(13, numbers[1]);
   }
@@ -731,7 +731,7 @@
     vector<int> numbers;
     EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
     ASSERT_EQ(2, numbers.size());
-    sort(numbers.begin(), numbers.end());
+    std::sort(numbers.begin(), numbers.end());
     EXPECT_EQ(12, numbers[0]);
     EXPECT_EQ(13, numbers[1]);
   }
diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py
deleted file mode 100644
index c5a8d8a..0000000
--- a/src/google/protobuf/descriptor_pb2_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#! /usr/bin/python
-#
-# 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.
-
-# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date.
-
-from google3.pyglib import resources
-from google.apputils import basetest
-
-_DESC = 'google3/net/proto2/proto/descriptor_pb2.'
-_OLD = _DESC + 'py-prebuilt'
-_NEW = _DESC + 'compiled'
-
-
-class PregeneratedFileChanged(basetest.TestCase):
-
-  def testSameText(self):
-    generated = resources.GetResource(_NEW)
-    checkedin = resources.GetResource(_OLD)
-    self.assertMultiLineEqual(
-        generated, checkedin, 'It seems that protoc _pb2 generator changed. '
-        'Please run google/protobuf/generate_descriptor_proto.sh to '
-        'regnerate a new version of %s and add it to your CL' % _OLD)
-
-if __name__ == '__main__':
-  basetest.main()
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 2ceb41e..fdce3d7 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -6104,9 +6104,9 @@
 
   file_desc->CopySourceCodeInfoTo(&file_desc_proto);
   const SourceCodeInfo& info = file_desc_proto.source_code_info();
-  ASSERT_EQ(3, info.location_size());
+  ASSERT_EQ(4, info.location_size());
   // Get the Foo message location
-  const SourceCodeInfo_Location& foo_location = info.location(1);
+  const SourceCodeInfo_Location& foo_location = info.location(2);
   ASSERT_EQ(2, foo_location.path_size());
   EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
   EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
new file mode 100644
index 0000000..868c732
--- /dev/null
+++ b/src/google/protobuf/duration.proto
@@ -0,0 +1,93 @@
+// 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 google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "DurationProto";
+option java_package = "com.google.protobuf";
+
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// Example 1: compute Duration from two Timestamps in pseudo code.
+//
+//     Timestamp start = ...;
+//     Timestamp end = ...;
+//     Duration duration = ...;
+//
+//     duration.seconds = end.seconds - start.seconds;
+//     duration.nanos = end.nanos - start.nanos;
+//
+//     if (duration.seconds < 0 && duration.nanos > 0) {
+//       duration.seconds += 1;
+//       duration.nanos -= 1000000000;
+//     } else if (durations.seconds > 0 && duration.nanos < 0) {
+//       duration.seconds -= 1;
+//       duration.nanos += 1000000000;
+//     }
+//
+// Example 2: compute Timestamp from Timestamp + Duration in pseudo code.
+//
+//     Timestamp start = ...;
+//     Duration duration = ...;
+//     Timestamp end = ...;
+//
+//     end.seconds = start.seconds + duration.seconds;
+//     end.nanos = start.nanos + duration.nanos;
+//
+//     if (end.nanos < 0) {
+//       end.seconds -= 1;
+//       end.nanos += 1000000000;
+//     } else if (end.nanos >= 1000000000) {
+//       end.seconds += 1;
+//       end.nanos -= 1000000000;
+//     }
+//
+message Duration {
+  // Signed seconds of the span of time. Must be from -315,576,000,000
+  // to +315,576,000,000 inclusive.
+  int64 seconds = 1;
+
+  // Signed fractions of a second at nanosecond resolution of the span
+  // of time. Durations less than one second are represented with a 0
+  // seconds field and a positive or negative nanos field. For durations
+  // of one second or more, a non-zero value for the nanos field must be
+  // of the same sign as the seconds field. Must be from -999,999,999
+  // to +999,999,999 inclusive.
+  int32 nanos = 2;
+}
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 4908713..03b38dd 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -97,7 +97,7 @@
               int number, ExtensionInfo info) {
   ::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry);
 
-  if (!InsertIfNotPresent(registry_, make_pair(containing_type, number),
+  if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number),
                           info)) {
     GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
                << containing_type->GetTypeName()
@@ -107,8 +107,9 @@
 
 const ExtensionInfo* FindRegisteredExtension(
     const MessageLite* containing_type, int number) {
-  return (registry_ == NULL) ? NULL :
-         FindOrNull(*registry_, make_pair(containing_type, number));
+  return (registry_ == NULL)
+             ? NULL
+             : FindOrNull(*registry_, std::make_pair(containing_type, number));
 }
 
 }  // namespace
@@ -1032,7 +1033,7 @@
 
   if (this_iter == extensions_.end()) {
     if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
-      extensions_.insert(make_pair(number, other_iter->second));
+      extensions_.insert(std::make_pair(number, other_iter->second));
     } else {
       InternalExtensionMergeFrom(number, other_iter->second);
     }
@@ -1042,7 +1043,7 @@
 
   if (other_iter == other->extensions_.end()) {
     if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
-      other->extensions_.insert(make_pair(number, this_iter->second));
+      other->extensions_.insert(std::make_pair(number, this_iter->second));
     } else {
       other->InternalExtensionMergeFrom(number, this_iter->second);
     }
@@ -1175,6 +1176,9 @@
                   extension.enum_validity_check.arg, value)) {
             AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed,
                     value, extension.descriptor);
+          } else {
+            // Invalid value.  Treat as unknown.
+            field_skipper->SkipUnknownEnum(number, value);
           }
         }
         break;
@@ -1337,7 +1341,7 @@
                                      const FieldDescriptor* descriptor,
                                      Extension** result) {
   pair<map<int, Extension>::iterator, bool> insert_result =
-    extensions_.insert(make_pair(number, Extension()));
+      extensions_.insert(std::make_pair(number, Extension()));
   *result = &insert_result.first->second;
   (*result)->descriptor = descriptor;
   return insert_result.second;
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 5f4ca1c..796e7a5 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -91,9 +91,10 @@
   const Descriptor* containing_type_;
 };
 
-void ExtensionSet::AppendToList(const Descriptor* containing_type,
-                                const DescriptorPool* pool,
-                                vector<const FieldDescriptor*>* output) const {
+void ExtensionSet::AppendToList(
+    const Descriptor* containing_type,
+    const DescriptorPool* pool,
+    std::vector<const FieldDescriptor*>* output) const {
   for (map<int, Extension>::const_iterator iter = extensions_.begin();
        iter != extensions_.end(); ++iter) {
     bool has = false;
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
new file mode 100644
index 0000000..492d4b0
--- /dev/null
+++ b/src/google/protobuf/field_mask.proto
@@ -0,0 +1,161 @@
+// 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 google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "FieldMaskProto";
+option java_package = "com.google.protobuf";
+
+
+// `FieldMask` represents a set of symbolic field paths, for example:
+//
+//     paths: "f.a"
+//     paths: "f.b.d"
+//
+// Here `f` represents a field in some root message, `a` and `b`
+// fields in the message found in `f`, and `d` a field found in the
+// message in `f.b`.
+//
+// Field masks are used to specify a subset of fields that should be
+// returned by a get operation or modified by an update operation.
+// Field masks also have a custom JSON encoding (see below).
+//
+// # Field Masks in Projections
+// When used in the context of a projection, a response message or
+// sub-message is filtered by the API to only contain those fields as
+// specified in the mask. For example, if the mask in the previous
+// example is applied to a response message as follows:
+//
+//     f {
+//       a : 22
+//       b {
+//         d : 1
+//         x : 2
+//       }
+//       y : 13
+//     }
+//     z: 8
+//
+// The result will not contain specific values for fields x,y and z
+// (there value will be set to the default, and omitted in proto text
+// output):
+//
+//
+//     f {
+//       a : 22
+//       b {
+//         d : 1
+//       }
+//     }
+//
+// A repeated field is not allowed except at the last position of a
+// field mask.
+//
+// If a FieldMask object is not present in a get operation, the
+// operation applies to all fields (as if a FieldMask of all fields
+// had been specified).
+//
+// Note that a field mask does not necessarily applies to the
+// top-level response message. In case of a REST get operation, the
+// field mask applies directly to the response, but in case of a REST
+// list operation, the mask instead applies to each individual message
+// in the returned resource list. In case of a REST custom method,
+// other definitions may be used. Where the mask applies will be
+// clearly documented together with its declaration in the API.  In
+// any case, the effect on the returned resource/resources is required
+// behavior for APIs.
+//
+// # Field Masks in Update Operations
+// A field mask in update operations specifies which fields of the
+// targeted resource are going to be updated. The API is required
+// to only change the values of the fields as specified in the mask
+// and leave the others untouched. If a resource is passed in to
+// describe the updated values, the API ignores the values of all
+// fields not covered by the mask.
+//
+// In order to reset a field's value to the default, the field must
+// be in the mask and set to the default value in the provided resource.
+// Hence, in order to reset all fields of a resource, provide a default
+// instance of the resource and set all fields in the mask, or do
+// not provide a mask as described below.
+//
+// If a field mask is not present on update, the operation applies to
+// all fields (as if a field mask of all fields has been specified).
+// Note that in the presence of schema evolution, this may mean that
+// fields the client does not know and has therefore not filled into
+// the request will be reset to their default. If this is unwanted
+// behavior, a specific service may require a client to always specify
+// a field mask, producing an error if not.
+//
+// As with get operations, the location of the resource which
+// describes the updated values in the request message depends on the
+// operation kind. In any case, the effect of the field mask is
+// required to be honored by the API.
+//
+// ## Considerations for HTTP REST
+// The HTTP kind of an update operation which uses a field mask must
+// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+// (PUT must only be used for full updates).
+//
+// # JSON Encoding of Field Masks
+// In JSON, a field mask is encoded as a single string where paths are
+// separated by a comma. Fields name in each path are converted
+// to/from lower-camel naming conventions.
+//
+// As an example, consider the following message declarations:
+//
+//     message Profile {
+//       User user = 1;
+//       Photo photo = 2;
+//     }
+//     message User {
+//       string display_name = 1;
+//       string address = 2;
+//     }
+//
+// In proto a field mask for `Profile` may look as such:
+//
+//     mask {
+//       paths: "user.display_name"
+//       paths: "photo"
+//     }
+//
+// In JSON, the same mask is represented as below:
+//
+//     {
+//       mask: "user.displayName,photo"
+//     }
+//
+message FieldMask {
+  // The set of field mask paths.
+  repeated string paths = 1;
+}
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
index 3852cea..fdcdc27 100644
--- a/src/google/protobuf/generated_enum_reflection.h
+++ b/src/google/protobuf/generated_enum_reflection.h
@@ -42,6 +42,7 @@
 #include <string>
 
 #include <google/protobuf/stubs/template_util.h>
+#include <google/protobuf/generated_enum_util.h>
 
 namespace google {
 namespace protobuf {
@@ -50,10 +51,6 @@
 
 namespace protobuf {
 
-// This type trait can be used to cause templates to only match proto2 enum
-// types.
-template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
-
 // Returns the EnumDescriptor for enum type E, which must be a
 // proto-declared enum type.  Code generated by the protocol compiler
 // will include specializations of this template for each enum type declared.
diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h
new file mode 100644
index 0000000..e424205
--- /dev/null
+++ b/src/google/protobuf/generated_enum_util.h
@@ -0,0 +1,46 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
+
+#include <google/protobuf/stubs/template_util.h>
+
+namespace google {
+namespace protobuf {
+
+// This type trait can be used to cause templates to only match proto2 enum
+// types.
+template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index b500b9c..412c48a 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -247,8 +247,14 @@
 UnknownFieldSet* empty_unknown_field_set_ = NULL;
 GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
 
+void DeleteEmptyUnknownFieldSet() {
+  delete empty_unknown_field_set_;
+  empty_unknown_field_set_ = NULL;
+}
+
 void InitEmptyUnknownFieldSet() {
   empty_unknown_field_set_ = new UnknownFieldSet;
+  internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
 }
 
 const UnknownFieldSet& GetEmptyUnknownFieldSet() {
@@ -989,6 +995,7 @@
   // Optimization:  The default instance never has any fields set.
   if (&message == default_instance_) return;
 
+  output->reserve(descriptor_->field_count());
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->is_repeated()) {
@@ -1012,7 +1019,7 @@
   }
 
   // ListFields() must sort output by field number.
-  sort(output->begin(), output->end(), FieldNumberSorter());
+  std::sort(output->begin(), output->end(), FieldNumberSorter());
 }
 
 // -------------------------------------------------------------------
@@ -1428,6 +1435,8 @@
 Message* GeneratedMessageReflection::MutableMessage(
     Message* message, const FieldDescriptor* field,
     MessageFactory* factory) const {
+  USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+
   if (factory == NULL) factory = message_factory_;
 
   if (field->is_extension()) {
@@ -1966,26 +1975,28 @@
   uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
   if (oneof_case > 0) {
     const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
-    switch (field->cpp_type()) {
-      case FieldDescriptor::CPPTYPE_STRING: {
-        switch (field->options().ctype()) {
-          default:  // TODO(kenton):  Support other string reps.
-          case FieldOptions::STRING: {
-            const string* default_ptr =
-                &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
-            MutableField<ArenaStringPtr>(message, field)->
-                Destroy(default_ptr, GetArena(message));
-            break;
+    if (GetArena(message) == NULL) {
+      switch (field->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_STRING: {
+          switch (field->options().ctype()) {
+            default:  // TODO(kenton):  Support other string reps.
+            case FieldOptions::STRING: {
+              const string* default_ptr =
+                  &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+              MutableField<ArenaStringPtr>(message, field)->
+                  Destroy(default_ptr, GetArena(message));
+              break;
+            }
           }
+          break;
         }
-        break;
-      }
 
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        delete *MutableRaw<Message*>(message, field);
-        break;
-      default:
-        break;
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          delete *MutableRaw<Message*>(message, field);
+          break;
+        default:
+          break;
+      }
     }
 
     *MutableOneofCase(message, oneof_descriptor) = 0;
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index df88205..93e1a22 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -153,7 +153,7 @@
 
 std::pair<CodedInputStream::Limit, int>
 CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
-  return make_pair(PushLimit(byte_limit), --recursion_budget_);
+  return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
 }
 
 bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
@@ -613,8 +613,15 @@
 }
 
 CodedOutputStream::~CodedOutputStream() {
+  Trim();
+}
+
+void CodedOutputStream::Trim() {
   if (buffer_size_ > 0) {
     output_->BackUp(buffer_size_);
+    total_bytes_ -= buffer_size_;
+    buffer_size_ = 0;
+    buffer_ = NULL;
   }
 }
 
@@ -662,12 +669,7 @@
       ) {
     WriteRaw(data, size);
   } else {
-    if (buffer_size_ > 0) {
-      output_->BackUp(buffer_size_);
-      total_bytes_ -= buffer_size_;
-      buffer_ = NULL;
-      buffer_size_ = 0;
-    }
+    Trim();
 
     total_bytes_ += size;
     had_error_ |= !output_->WriteAliasedRaw(data, size);
@@ -704,61 +706,12 @@
   }
 }
 
-inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
-    uint32 value, uint8* target) {
-  target[0] = static_cast<uint8>(value | 0x80);
-  if (value >= (1 << 7)) {
-    target[1] = static_cast<uint8>((value >>  7) | 0x80);
-    if (value >= (1 << 14)) {
-      target[2] = static_cast<uint8>((value >> 14) | 0x80);
-      if (value >= (1 << 21)) {
-        target[3] = static_cast<uint8>((value >> 21) | 0x80);
-        if (value >= (1 << 28)) {
-          target[4] = static_cast<uint8>(value >> 28);
-          return target + 5;
-        } else {
-          target[3] &= 0x7F;
-          return target + 4;
-        }
-      } else {
-        target[2] &= 0x7F;
-        return target + 3;
-      }
-    } else {
-      target[1] &= 0x7F;
-      return target + 2;
-    }
-  } else {
-    target[0] &= 0x7F;
-    return target + 1;
-  }
-}
-
-void CodedOutputStream::WriteVarint32(uint32 value) {
-  if (buffer_size_ >= kMaxVarint32Bytes) {
-    // Fast path:  We have enough bytes left in the buffer to guarantee that
-    // this write won't cross the end, so we can skip the checks.
-    uint8* target = buffer_;
-    uint8* end = WriteVarint32FallbackToArrayInline(value, target);
-    int size = end - target;
-    Advance(size);
-  } else {
-    // Slow path:  This write might cross the end of the buffer, so we
-    // compose the bytes first then use WriteRaw().
-    uint8 bytes[kMaxVarint32Bytes];
-    int size = 0;
-    while (value > 0x7F) {
-      bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
-      value >>= 7;
-    }
-    bytes[size++] = static_cast<uint8>(value) & 0x7F;
-    WriteRaw(bytes, size);
-  }
-}
-
-uint8* CodedOutputStream::WriteVarint32FallbackToArray(
-    uint32 value, uint8* target) {
-  return WriteVarint32FallbackToArrayInline(value, target);
+void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
+  uint8 bytes[kMaxVarint32Bytes];
+  uint8* target = &bytes[0];
+  uint8* end = WriteVarint32ToArray(value, target);
+  int size = end - target;
+  WriteRaw(bytes, size);
 }
 
 inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 978cc19..dea4b65 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -647,6 +647,13 @@
   // ZeroCopyOutputStream immediately after the last byte written.
   ~CodedOutputStream();
 
+  // Trims any unused space in the underlying buffer so that its size matches
+  // the number of bytes written by this stream. The underlying buffer will
+  // automatically be trimmed when this stream is destroyed; this call is only
+  // necessary if the underlying buffer is accessed *before* the stream is
+  // destroyed.
+  void Trim();
+
   // Skips a number of bytes, leaving the bytes unmodified in the underlying
   // buffer.  Returns false if an underlying write error occurs.  This is
   // mainly useful with GetDirectBufferPointer().
@@ -789,7 +796,9 @@
   // ZeroCopyOutputStream supports it.
   void WriteAliasedRaw(const void* buffer, int size);
 
-  static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target);
+  // If this write might cross the end of the buffer, we compose the bytes first
+  // then use WriteRaw().
+  void WriteVarint32SlowPath(uint32 value);
 
   // Always-inlined versions of WriteVarint* functions so that code can be
   // reused, while still controlling size. For instance, WriteVarint32ToArray()
@@ -798,8 +807,6 @@
   // WriteVarint32FallbackToArray.  Meanwhile, WriteVarint32() is already
   // out-of-line, so it should just invoke this directly to avoid any extra
   // function call overhead.
-  static uint8* WriteVarint32FallbackToArrayInline(
-      uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
   static uint8* WriteVarint64ToArrayInline(
       uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
 
@@ -919,7 +926,7 @@
       const uint32 kMax1ByteVarint = 0x7f;
       uint32 tag = last_tag_ = buffer_[0];
       Advance(1);
-      return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
+      return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
     }
     // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available,
     // and tag is two bytes.  The latter is tested by bitwise-and-not of the
@@ -937,12 +944,12 @@
       // so we don't have to check for tag == 0.  We may need to check whether
       // it exceeds cutoff.
       bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff;
-      return make_pair(tag, at_or_below_cutoff);
+      return std::make_pair(tag, at_or_below_cutoff);
     }
   }
   // Slow path
   last_tag_ = ReadTagFallback();
-  return make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
+  return std::make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
 }
 
 inline bool CodedInputStream::LastTagWas(uint32 expected) {
@@ -1027,13 +1034,14 @@
 }
 
 inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value,
-                                                        uint8* target) {
-  if (value < 0x80) {
-    *target = value;
-    return target + 1;
-  } else {
-    return WriteVarint32FallbackToArray(value, target);
+                                                      uint8* target) {
+  while (value >= 0x80) {
+    *target = static_cast<uint8>(value | 0x80);
+    value >>= 7;
+    ++target;
   }
+  *target = static_cast<uint8>(value);
+  return target + 1;
 }
 
 inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) {
@@ -1086,22 +1094,26 @@
   return target + sizeof(value);
 }
 
+inline void CodedOutputStream::WriteVarint32(uint32 value) {
+  if (buffer_size_ >= 5) {
+    // Fast path:  We have enough bytes left in the buffer to guarantee that
+    // this write won't cross the end, so we can skip the checks.
+    uint8* target = buffer_;
+    uint8* end = WriteVarint32ToArray(value, target);
+    int size = end - target;
+    Advance(size);
+  } else {
+    WriteVarint32SlowPath(value);
+  }
+}
+
 inline void CodedOutputStream::WriteTag(uint32 value) {
   WriteVarint32(value);
 }
 
 inline uint8* CodedOutputStream::WriteTagToArray(
     uint32 value, uint8* target) {
-  if (value < (1 << 7)) {
-    target[0] = value;
-    return target + 1;
-  } else if (value < (1 << 14)) {
-    target[0] = static_cast<uint8>(value | 0x80);
-    target[1] = static_cast<uint8>(value >> 7);
-    return target + 2;
-  } else {
-    return WriteVarint32FallbackToArray(value, target);
-  }
+  return WriteVarint32ToArray(value, target);
 }
 
 inline int CodedOutputStream::VarintSize32(uint32 value) {
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index bbe5e39..02d5bad 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -502,11 +502,11 @@
 };
 
 inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) {
-  return os << "0x" << hex << c.value << dec;
+  return os << "0x" << std::hex << c.value << std::dec;
 }
 
 inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) {
-  return os << "0x" << hex << c.value << dec;
+  return os << "0x" << std::hex << c.value << std::dec;
 }
 
 Fixed32Case kFixed32Cases[] = {
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index e603786..c9f4ca7 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -49,6 +49,7 @@
 GzipInputStream::GzipInputStream(
     ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
     : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) {
+  zcontext_.state = Z_NULL;
   zcontext_.zalloc = Z_NULL;
   zcontext_.zfree = Z_NULL;
   zcontext_.opaque = Z_NULL;
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 3e25edf..4360b18 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -368,7 +368,7 @@
 inline std::pair<char*, bool> as_string_data(string* s) {
   char *p = mutable_string_data(s);
 #ifdef LANG_CXX11
-  return make_pair(p, true);
+  return std::make_pair(p, true);
 #else
   return make_pair(p, p != NULL);
 #endif
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index a370526..4ea2100 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -345,6 +345,6 @@
     GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size());
   }
 
-  cout << "PASS" << endl;
+  std::cout << "PASS" << std::endl;
   return 0;
 }
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 6d8a9d0..e56af3f 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -34,6 +34,8 @@
 #include <iterator>
 #include <google/protobuf/stubs/hash.h>
 
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_enum_util.h>
 #include <google/protobuf/map_type_handler.h>
 
 namespace google {
@@ -45,10 +47,12 @@
 template <typename Enum> struct is_proto_enum;
 
 namespace internal {
-template <typename K, typename V, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-class MapField;
-}  // namespace internal
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+class MapFieldLite;
+}
 
 // This is the class for google::protobuf::Map's internal value_type. Instead of using
 // std::pair as value_type, we use this class which provides us more control of
@@ -61,23 +65,24 @@
 
   MapPair(const Key& other_first, const T& other_second)
       : first(other_first), second(other_second) {}
-
   explicit MapPair(const Key& other_first) : first(other_first), second() {}
-
   MapPair(const MapPair& other)
       : first(other.first), second(other.second) {}
 
   ~MapPair() {}
 
-  // Implicitly convertible to std::pair.
-  operator std::pair<const Key, T>() const {
-    return std::pair<const Key, T>(first, second);
+  // Implicitly convertible to std::pair of compatible types.
+  template <typename T1, typename T2>
+  operator std::pair<T1, T2>() const {
+    return std::pair<T1, T2>(first, second);
   }
 
   const Key first;
   T second;
 
  private:
+  typedef void DestructorSkippable_;
+  friend class ::google::protobuf::Arena;
   friend class Map<Key, T>;
 };
 
@@ -86,6 +91,7 @@
 // interface directly to visit or change map fields.
 template <typename Key, typename T>
 class Map {
+  typedef internal::MapCppTypeHandler<Key> KeyTypeHandler;
   typedef internal::MapCppTypeHandler<T> ValueTypeHandler;
 
  public:
@@ -100,20 +106,104 @@
 
   typedef size_t size_type;
   typedef hash<Key> hasher;
+  typedef equal_to<Key> key_equal;
 
-  Map() : default_enum_value_(0) {}
+  Map()
+      : arena_(NULL),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(0) {}
+  explicit Map(Arena* arena)
+      : arena_(arena),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(0) {}
 
-  Map(const Map& other) {
+  Map(const Map& other)
+      : arena_(NULL),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(other.default_enum_value_) {
     insert(other.begin(), other.end());
   }
 
   ~Map() { clear(); }
 
+ private:
+  // re-implement std::allocator to use arena allocator for memory allocation.
+  // Used for google::protobuf::Map implementation. Users should not use this class
+  // directly.
+  template <typename U>
+  class MapAllocator {
+   public:
+    typedef U value_type;
+    typedef value_type* pointer;
+    typedef const value_type* const_pointer;
+    typedef value_type& reference;
+    typedef const value_type& const_reference;
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+
+    MapAllocator() : arena_(NULL) {}
+    explicit MapAllocator(Arena* arena) : arena_(arena) {}
+    template <typename X>
+    MapAllocator(const MapAllocator<X>& allocator)
+        : arena_(allocator.arena_) {}
+
+    pointer allocate(size_type n, const_pointer hint = 0) {
+      // If arena is not given, malloc needs to be called which doesn't
+      // construct element object.
+      if (arena_ == NULL) {
+        return reinterpret_cast<pointer>(malloc(n * sizeof(value_type)));
+      } else {
+        return reinterpret_cast<pointer>(
+            Arena::CreateArray<uint8>(arena_, n * sizeof(value_type)));
+      }
+    }
+
+    void deallocate(pointer p, size_type n) {
+      if (arena_ == NULL) {
+        free(p);
+      }
+    }
+
+    void construct(pointer p, const_reference t) { new (p) value_type(t); }
+
+    void destroy(pointer p) {
+      if (arena_ == NULL) p->~value_type();
+    }
+
+    template <typename X>
+    struct rebind {
+      typedef MapAllocator<X> other;
+    };
+
+    template <typename X>
+    bool operator==(const MapAllocator<X>& other) const {
+      return arena_ == other.arena_;
+    }
+
+    template <typename X>
+    bool operator!=(const MapAllocator<X>& other) const {
+      return arena_ != other.arena_;
+    }
+
+   private:
+    Arena* arena_;
+
+    template <typename X>
+    friend class MapAllocator;
+  };
+
+ public:
+  typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
+
   // Iterators
-  class const_iterator
+  class LIBPROTOBUF_EXPORT const_iterator
       : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
                              const value_type*, const value_type&> {
-    typedef typename hash_map<Key, value_type*>::const_iterator InnerIt;
+    typedef typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+                              Allocator>::const_iterator InnerIt;
 
    public:
     const_iterator() {}
@@ -139,8 +229,9 @@
     InnerIt it_;
   };
 
-  class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
-    typedef typename hash_map<Key, value_type*>::iterator InnerIt;
+  class LIBPROTOBUF_EXPORT iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+    typedef typename hash_map<Key, value_type*, hasher, equal_to<Key>,
+                              Allocator>::iterator InnerIt;
 
    public:
     iterator() {}
@@ -185,7 +276,7 @@
   T& operator[](const key_type& key) {
     value_type** value = &elements_[key];
     if (*value == NULL) {
-      *value = new value_type(key);
+      *value = CreateValueTypeInternal(key);
       internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
                                     T>::Initialize((*value)->second,
                                                    default_enum_value_);
@@ -241,7 +332,7 @@
     } else {
       return std::pair<iterator, bool>(
           iterator(elements_.insert(std::pair<Key, value_type*>(
-              value.first, new value_type(value))).first), true);
+              value.first, CreateValueTypeInternal(value))).first), true);
     }
   }
   template <class InputIt>
@@ -256,28 +347,29 @@
 
   // Erase
   size_type erase(const key_type& key) {
-    typename hash_map<Key, value_type*>::iterator it = elements_.find(key);
+    typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+                      Allocator>::iterator it = elements_.find(key);
     if (it == elements_.end()) {
       return 0;
     } else {
-      delete it->second;
+      if (arena_ == NULL) delete it->second;
       elements_.erase(it);
       return 1;
     }
   }
   void erase(iterator pos) {
-    delete pos.it_->second;
+    if (arena_ == NULL) delete pos.it_->second;
     elements_.erase(pos.it_);
   }
   void erase(iterator first, iterator last) {
     for (iterator it = first; it != last;) {
-      delete it.it_->second;
+      if (arena_ == NULL) delete it.it_->second;
       elements_.erase((it++).it_);
     }
   }
   void clear() {
     for (iterator it = begin(); it != end(); ++it) {
-      delete it.it_->second;
+      if (arena_ == NULL) delete it.it_->second;
     }
     elements_.clear();
   }
@@ -297,12 +389,45 @@
     default_enum_value_ = default_enum_value;
   }
 
-  hash_map<Key, value_type*> elements_;
+  value_type* CreateValueTypeInternal(const Key& key) {
+    if (arena_ == NULL) {
+      return new value_type(key);
+    } else {
+      value_type* value = reinterpret_cast<value_type*>(
+          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+      Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_);
+      Arena::CreateInArenaStorage(&value->second, arena_);
+      const_cast<Key&>(value->first) = key;
+      return value;
+    }
+  }
+
+  value_type* CreateValueTypeInternal(const value_type& value) {
+    if (arena_ == NULL) {
+      return new value_type(value);
+    } else {
+      value_type* p = reinterpret_cast<value_type*>(
+          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+      Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_);
+      Arena::CreateInArenaStorage(&p->second, arena_);
+      const_cast<Key&>(p->first) = value.first;
+      p->second = value.second;
+      return p;
+    }
+  }
+
+  Arena* arena_;
+  Allocator allocator_;
+  hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator> elements_;
   int default_enum_value_;
 
-  template <typename K, typename V, FieldDescriptor::Type KeyProto,
-            FieldDescriptor::Type ValueProto, int default_enum>
-  friend class internal::MapField;
+  friend class ::google::protobuf::Arena;
+  typedef void DestructorSkippable_;
+  template <typename K, typename V,
+            internal::WireFormatLite::FieldType key_wire_type,
+            internal::WireFormatLite::FieldType value_wire_type,
+            int default_enum_value>
+  friend class LIBPROTOBUF_EXPORT internal::MapFieldLite;
 };
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 217b15f..f78a4f4 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -31,13 +31,23 @@
 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
 #define GOOGLE_PROTOBUF_MAP_ENTRY_H__
 
-#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/map_entry_lite.h>
 #include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 
 namespace google {
 namespace protobuf {
 class Arena;
+namespace internal {
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapField;
+}
 }
 
 namespace protobuf {
@@ -45,7 +55,8 @@
 
 // Register all MapEntry default instances so we can delete them in
 // ShutdownProtobufLibrary().
-void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(MessageLite* default_instance);
+void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
+    MessageLite* default_instance);
 
 // This is the common base class for MapEntry. It is used by MapFieldBase in
 // reflection api, in which the static type of key and value is unknown.
@@ -82,179 +93,103 @@
 // while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
 // get internal layout.
 // Moreover, default_enum_value is used to initialize enum field in proto2.
-template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
-          FieldDescriptor::Type ValueProtoType, int default_enum_value>
-class MapEntry : public MapEntryBase {
-  // Handlers for key/value's proto field type. Used to infer internal layout
-  // and provide parsing/serialization support.
-  typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler;
-  typedef MapProtoTypeHandler<ValueProtoType> ValueProtoHandler;
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
+  // Handlers for key/value wire type. Provide utilities to parse/serialize
+  // key/value.
+  typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+  typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
 
   // Define key/value's internal stored type. Message is the only one whose
   // internal stored type cannot be inferred from its proto type.
-  typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType;
-  typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType;
-  static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
-  static const bool kIsValueMessage = ValueProtoHandler::kIsMessage;
-  typedef typename MapIf<kIsKeyMessage, Key, KeyProtoHandlerCppType>::type
+  static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+  static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
+  typedef typename KeyWireHandler::CppType KeyInternalType;
+  typedef typename ValueWireHandler::CppType ValueInternalType;
+  typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
       KeyCppType;
-  typedef typename MapIf<kIsValueMessage, Value, ValueProtoHandlerCppType>::type
+  typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
       ValCppType;
 
-  // Handlers for key/value's internal stored type. Provide utilities to
-  // manipulate internal stored type. We need it because some types are stored
-  // as values and others are stored as pointers (Message and string), but we
-  // need to keep the code in MapEntry unified instead of providing different
-  // codes for each type.
-  typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
-  typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
-
-  // Define internal memory layout. Strings and messages are stored as
-  // pointers, while other types are stored as values.
-  static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
-  static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
-  typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
-      KeyBase;
-  typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
-      ValueBase;
-
   // Abbreviation for MapEntry
   typedef typename google::protobuf::internal::MapEntry<
-      Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType;
+      Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
 
-  // Constants for field number.
-  static const int kKeyFieldNumber = 1;
-  static const int kValueFieldNumber = 2;
-
-  // Constants for field tag.
-  static const uint8 kKeyTag   = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
-      kKeyFieldNumber,   KeyProtoHandler::kWireType);
-  static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
-      kValueFieldNumber, ValueProtoHandler::kWireType);
-  static const int kTagSize = 1;
+  // Abbreviation for MapEntryLite
+  typedef typename google::protobuf::internal::MapEntryLite<
+      Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
+      EntryLiteType;
 
  public:
   ~MapEntry() {
     if (this == default_instance_) {
       delete reflection_;
-    } else {
-      KeyCppHandler::Delete(key_);
-      ValueCppHandler::Delete(value_);
     }
   }
 
   // accessors ======================================================
 
-  inline void set_key(const KeyCppType& key) {
-    KeyCppHandler::EnsureMutable(&key_);
-    KeyCppHandler::Merge(key, &key_);
-    set_has_key();
-  }
   virtual inline const KeyCppType& key() const {
-    return KeyCppHandler::Reference(key_);
+    return entry_lite_.key();
   }
   inline KeyCppType* mutable_key() {
-    set_has_key();
-    KeyCppHandler::EnsureMutable(&key_);
-    return KeyCppHandler::Pointer(key_);
-  }
-  inline void set_value(const ValCppType& value) {
-    ValueCppHandler::EnsureMutable(&value_);
-    ValueCppHandler::Merge(value, &value_);
-    set_has_value();
+    return entry_lite_.mutable_key();
   }
   virtual inline const ValCppType& value() const {
-    GOOGLE_CHECK(default_instance_ != NULL);
-    return ValueCppHandler::DefaultIfNotInitialized(value_,
-                                               default_instance_->value_);
+    return entry_lite_.value();
   }
   inline ValCppType* mutable_value() {
-    set_has_value();
-    ValueCppHandler::EnsureMutable(&value_);
-    return ValueCppHandler::Pointer(value_);
+    return entry_lite_.mutable_value();
   }
 
   // implements Message =============================================
 
   bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
-    uint32 tag;
-
-    for (;;) {
-      // 1) corrupted data: return false;
-      // 2) unknown field: skip without putting into unknown field set;
-      // 3) unknown enum value: keep it in parsing. In proto2, caller should
-      // check the value and put this entry into containing message's unknown
-      // field set if the value is an unknown enum. In proto3, caller doesn't
-      // need to care whether the value is unknown enum;
-      // 4) missing key/value: missed key/value will have default value. caller
-      // should take this entry as if key/value is set to default value.
-      tag = input->ReadTag();
-      switch (tag) {
-        case kKeyTag:
-          if (!KeyProtoHandler::Read(input, mutable_key())) return false;
-          set_has_key();
-          if (!input->ExpectTag(kValueTag)) break;
-          GOOGLE_FALLTHROUGH_INTENDED;
-
-        case kValueTag:
-          if (!ValueProtoHandler::Read(input, mutable_value())) return false;
-          set_has_value();
-          if (input->ExpectAtEnd()) return true;
-          break;
-
-        default:
-          if (tag == 0 ||
-              WireFormatLite::GetTagWireType(tag) ==
-              WireFormatLite::WIRETYPE_END_GROUP) {
-            return true;
-          }
-          if (!WireFormatLite::SkipField(input, tag)) return false;
-          break;
-      }
-    }
+    return entry_lite_.MergePartialFromCodedStream(input);
   }
 
   int ByteSize() const {
-    int size = 0;
-    size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0;
-    size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0;
-    return size;
+    return entry_lite_.ByteSize();
   }
 
   void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
-    KeyProtoHandler::Write(kKeyFieldNumber, key(), output);
-    ValueProtoHandler::Write(kValueFieldNumber, value(), output);
+    entry_lite_.SerializeWithCachedSizes(output);
   }
 
   ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
-    output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output);
-    output =
-        ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output);
-    return output;
+    return entry_lite_.SerializeWithCachedSizesToArray(output);
   }
 
   int GetCachedSize() const {
-    int size = 0;
-    size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0;
-    size +=
-        has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0;
-    return size;
+    return entry_lite_.GetCachedSize();
   }
 
-  bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+  bool IsInitialized() const {
+    return entry_lite_.IsInitialized();
+  }
 
   Message* New() const {
     MapEntry* entry = new MapEntry;
     entry->descriptor_ = descriptor_;
     entry->reflection_ = reflection_;
-    entry->default_instance_ = default_instance_;
+    entry->set_default_instance(default_instance_);
+    return entry;
+  }
+
+  Message* New(Arena* arena) const {
+    MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
+    entry->descriptor_ = descriptor_;
+    entry->reflection_ = reflection_;
+    entry->set_default_instance(default_instance_);
     return entry;
   }
 
   int SpaceUsed() const {
     int size = sizeof(MapEntry);
-    size += KeyCppHandler::SpaceUsedInMapEntry(key_);
-    size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+    size += entry_lite_.SpaceUsed();
     return size;
   }
 
@@ -279,30 +214,19 @@
   }
 
   void MergeFrom(const MapEntry& from) {
-    if (from._has_bits_[0]) {
-      if (from.has_key()) {
-        KeyCppHandler::EnsureMutable(&key_);
-        KeyCppHandler::Merge(from.key(), &key_);
-        set_has_key();
-      }
-      if (from.has_value()) {
-        ValueCppHandler::EnsureMutable(&value_);
-        ValueCppHandler::Merge(from.value(), &value_);
-        set_has_value();
-      }
-    }
+    entry_lite_.MergeFrom(from.entry_lite_);
   }
 
   void Clear() {
-    KeyCppHandler::Clear(&key_);
-    ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
-    clear_has_key();
-    clear_has_value();
+    entry_lite_.Clear();
   }
 
   void InitAsDefaultInstance() {
-    KeyCppHandler::AssignDefaultValue(&key_);
-    ValueCppHandler::AssignDefaultValue(&value_);
+    entry_lite_.InitAsDefaultInstance();
+  }
+
+  Arena* GetArena() const {
+    return entry_lite_.GetArena();
   }
 
   // Create default MapEntry instance for given descriptor. Descriptor has to be
@@ -310,141 +234,58 @@
   // may have the same type and MapEntry class. The given descriptor is needed
   // to distinguish instances of the same MapEntry class.
   static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
-    MapEntry* entry = new MapEntry();
+    MapEntry* entry = new MapEntry;
     const Reflection* reflection = new GeneratedMessageReflection(
         descriptor, entry, offsets_,
-        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_),
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
         GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
         DescriptorPool::generated_pool(),
         ::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
     entry->descriptor_ = descriptor;
     entry->reflection_ = reflection;
-    entry->default_instance_ = entry;
+    entry->set_default_instance(entry);
     entry->InitAsDefaultInstance();
     RegisterMapEntryDefaultInstance(entry);
     return entry;
   }
 
-  // Create a MapEntry for given key and value from google::protobuf::Map in
-  // serialization. This function is only called when value is enum. Enum is
-  // treated differently because its type in MapEntry is int and its type in
-  // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
-  static MapEntry* EnumWrap(const Key& key, const Value value) {
-    return new MapEnumEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
-                                   default_enum_value>(key, value);
-  }
-
-  // Like above, but for all the other types. This avoids value copy to create
-  // MapEntry from google::protobuf::Map in serialization.
-  static MapEntry* Wrap(const Key& key, const Value& value) {
-    return new MapEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
-                               default_enum_value>(key, value);
-  }
-
- protected:
-  void set_has_key() { _has_bits_[0] |= 0x00000001u; }
-  bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
-  void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
-  void set_has_value() { _has_bits_[0] |= 0x00000002u; }
-  bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
-  void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
-
  private:
-  // Serializing a generated message containing map field involves serializing
-  // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
-  // after serialization should be the same as that of a MapEntry message
-  // containing the same key and value inside it.  However, google::protobuf::Map doesn't
-  // store key and value as MapEntry message, which disables us to use existing
-  // code to serialize message. In order to use existing code to serialize
-  // message, we need to construct a MapEntry from key-value pair. But it
-  // involves copy of key and value to construct a MapEntry. In order to avoid
-  // this copy in constructing a MapEntry, we need the following class which
-  // only takes references of given key and value.
-  template <typename KeyNested, typename ValueNested,
-            FieldDescriptor::Type KeyProtoNested,
-            FieldDescriptor::Type ValueProtoNested, int default_enum>
-  class MapEntryWrapper
-      : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
-                        ValueProtoNested, default_enum> {
-    typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
-                     default_enum_value> Base;
-    typedef typename Base::KeyCppType KeyCppType;
-    typedef typename Base::ValCppType ValCppType;
+  MapEntry() : default_instance_(NULL), entry_lite_() {}
 
-   public:
-    MapEntryWrapper(const KeyNested& key, const ValueNested& value)
-        : key_(key), value_(value) {
-      Base::set_has_key();
-      Base::set_has_value();
-    }
-    inline const KeyCppType& key() const { return key_; }
-    inline const ValCppType& value() const { return value_; }
+  explicit MapEntry(Arena* arena)
+      : default_instance_(NULL), entry_lite_(arena) {}
 
-   private:
-    const Key& key_;
-    const Value& value_;
-  };
-
-  // Like above, but for enum value only, which stores value instead of
-  // reference of value field inside. This is needed because the type of value
-  // field in constructor is an enum, while we need to store it as an int. If we
-  // initialize a reference to int with a reference to enum, compiler will
-  // generate a temporary int from enum and initialize the reference to int with
-  // the temporary.
-  template <typename KeyNested, typename ValueNested,
-            FieldDescriptor::Type KeyProtoNested,
-            FieldDescriptor::Type ValueProtoNested, int default_enum>
-  class MapEnumEntryWrapper
-      : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
-                        ValueProtoNested, default_enum> {
-    typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
-                     default_enum> Base;
-    typedef typename Base::KeyCppType KeyCppType;
-    typedef typename Base::ValCppType ValCppType;
-
-   public:
-    MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value)
-        : key_(key), value_(value) {
-      Base::set_has_key();
-      Base::set_has_value();
-    }
-    inline const KeyCppType& key() const { return key_; }
-    inline const ValCppType& value() const { return value_; }
-
-   private:
-    const KeyCppType& key_;
-    const ValCppType value_;
-  };
-
-  MapEntry() : default_instance_(NULL) {
-    KeyCppHandler::Initialize(&key_);
-    ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value);
-    _has_bits_[0] = 0;
+  inline Arena* GetArenaNoVirtual() const {
+    return entry_lite_.GetArenaNoVirtual();
   }
 
-  KeyBase key_;
-  ValueBase value_;
+  void set_default_instance(MapEntry* default_instance) {
+    default_instance_ = default_instance;
+    entry_lite_.set_default_instance(&default_instance->entry_lite_);
+  }
+
   static int offsets_[2];
   UnknownFieldSet _unknown_fields_;
-  uint32 _has_bits_[1];
   MapEntry* default_instance_;
+  EntryLiteType entry_lite_;
 
   friend class ::google::protobuf::Arena;
-  template <typename K, typename V,
-            FieldDescriptor::Type KType,
-            FieldDescriptor::Type VType, int default_enum>
-  friend class internal::MapField;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+            WireFormatLite::FieldType, int default_enum>
+  friend class LIBPROTOBUF_EXPORT internal::MapField;
   friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
 };
 
-template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
-          FieldDescriptor::Type ValueProtoType, int default_enum_value>
-int MapEntry<Key, Value, KeyProtoType, ValueProtoType,
+template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
              default_enum_value>::offsets_[2] = {
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
 };
 
 }  // namespace internal
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
new file mode 100644
index 0000000..304fba8
--- /dev/null
+++ b/src/google/protobuf/map_entry_lite.h
@@ -0,0 +1,409 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
+
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+class Arena;
+namespace internal {
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapEntry;
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapFieldLite;
+}  // namespace internal
+}  // namespace protobuf
+
+namespace protobuf {
+namespace internal {
+
+// MapEntryLite is used to implement parsing and serialization of map for lite
+// runtime.
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
+  // Handlers for key/value wire type. Provide utilities to parse/serialize
+  // key/value.
+  typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+  typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
+
+  // Define key/value's internal stored type. Message is the only one whose
+  // internal stored type cannot be inferred from its proto type
+  static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+  static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
+  typedef typename KeyWireHandler::CppType KeyInternalType;
+  typedef typename ValueWireHandler::CppType ValueInternalType;
+  typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
+      KeyCppType;
+  typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
+      ValCppType;
+
+  // Handlers for key/value's internal stored type. Provide utilities to
+  // manipulate internal stored type. We need it because some types are stored
+  // as values and others are stored as pointers (Message and string), but we
+  // need to keep the code in MapEntry unified instead of providing different
+  // codes for each type.
+  typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
+  typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
+
+  // Define internal memory layout. Strings and messages are stored as
+  // pointers, while other types are stored as values.
+  static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
+  static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
+  typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
+      KeyBase;
+  typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
+      ValueBase;
+
+  // Constants for field number.
+  static const int kKeyFieldNumber = 1;
+  static const int kValueFieldNumber = 2;
+
+  // Constants for field tag.
+  static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+      kKeyFieldNumber, KeyWireHandler::kWireType);
+  static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+      kValueFieldNumber, ValueWireHandler::kWireType);
+  static const int kTagSize = 1;
+
+ public:
+  ~MapEntryLite() {
+    if (this != default_instance_) {
+      KeyCppHandler::Delete(key_);
+      ValueCppHandler::Delete(value_);
+    }
+  }
+
+  // accessors ======================================================
+
+  virtual inline const KeyCppType& key() const {
+    return KeyCppHandler::Reference(key_);
+  }
+  inline KeyCppType* mutable_key() {
+    set_has_key();
+    KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+    return KeyCppHandler::Pointer(key_);
+  }
+  virtual inline const ValCppType& value() const {
+    GOOGLE_CHECK(default_instance_ != NULL);
+    return ValueCppHandler::DefaultIfNotInitialized(value_,
+                                                    default_instance_->value_);
+  }
+  inline ValCppType* mutable_value() {
+    set_has_value();
+    ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+    return ValueCppHandler::Pointer(value_);
+  }
+
+  // implements MessageLite =========================================
+
+  // MapEntryLite is for implementation only and this function isn't called
+  // anywhere. Just provide a fake implementation here for MessageLite.
+  string GetTypeName() const { return ""; }
+
+  void CheckTypeAndMergeFrom(const MessageLite& other) {
+    MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
+  }
+
+  bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+    uint32 tag;
+
+    for (;;) {
+      // 1) corrupted data: return false;
+      // 2) unknown field: skip without putting into unknown field set;
+      // 3) unknown enum value: keep it in parsing. In proto2, caller should
+      // check the value and put this entry into containing message's unknown
+      // field set if the value is an unknown enum. In proto3, caller doesn't
+      // need to care whether the value is unknown enum;
+      // 4) missing key/value: missed key/value will have default value. caller
+      // should take this entry as if key/value is set to default value.
+      tag = input->ReadTag();
+      switch (tag) {
+        case kKeyTag:
+          if (!KeyWireHandler::Read(input, mutable_key())) return false;
+          set_has_key();
+          if (!input->ExpectTag(kValueTag)) break;
+          GOOGLE_FALLTHROUGH_INTENDED;
+
+        case kValueTag:
+          if (!ValueWireHandler::Read(input, mutable_value())) return false;
+          set_has_value();
+          if (input->ExpectAtEnd()) return true;
+          break;
+
+        default:
+          if (tag == 0 ||
+              WireFormatLite::GetTagWireType(tag) ==
+              WireFormatLite::WIRETYPE_END_GROUP) {
+            return true;
+          }
+          if (!WireFormatLite::SkipField(input, tag)) return false;
+          break;
+      }
+    }
+  }
+
+  int ByteSize() const {
+    int size = 0;
+    size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0;
+    size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0;
+    return size;
+  }
+
+  void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+    KeyWireHandler::Write(kKeyFieldNumber, key(), output);
+    ValueWireHandler::Write(kValueFieldNumber, value(), output);
+  }
+
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
+    output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output);
+    output =
+        ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output);
+    return output;
+  }
+
+  int GetCachedSize() const {
+    int size = 0;
+    size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0;
+    size +=
+        has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0;
+    return size;
+  }
+
+  bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+
+  MessageLite* New() const {
+    MapEntryLite* entry = new MapEntryLite;
+    entry->default_instance_ = default_instance_;
+    return entry;
+  }
+
+  MessageLite* New(Arena* arena) const {
+    MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
+    entry->default_instance_ = default_instance_;
+    return entry;
+  }
+
+  int SpaceUsed() const {
+    int size = sizeof(MapEntryLite);
+    size += KeyCppHandler::SpaceUsedInMapEntry(key_);
+    size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+    return size;
+  }
+
+  void MergeFrom(const MapEntryLite& from) {
+    if (from._has_bits_[0]) {
+      if (from.has_key()) {
+        KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+        KeyCppHandler::Merge(from.key(), &key_);
+        set_has_key();
+      }
+      if (from.has_value()) {
+        ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+        ValueCppHandler::Merge(from.value(), &value_);
+        set_has_value();
+      }
+    }
+  }
+
+  void Clear() {
+    KeyCppHandler::Clear(&key_);
+    ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
+    clear_has_key();
+    clear_has_value();
+  }
+
+  void InitAsDefaultInstance() {
+    KeyCppHandler::AssignDefaultValue(&key_);
+    ValueCppHandler::AssignDefaultValue(&value_);
+  }
+
+  Arena* GetArena() const {
+    return GetArenaNoVirtual();
+  }
+
+  // Create a MapEntryLite for given key and value from google::protobuf::Map in
+  // serialization. This function is only called when value is enum. Enum is
+  // treated differently because its type in MapEntry is int and its type in
+  // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
+  static MapEntryLite* EnumWrap(const Key& key, const Value value,
+                                Arena* arena) {
+    return Arena::Create<MapEnumEntryWrapper<
+        Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
+        arena, key, value, arena);
+  }
+
+  // Like above, but for all the other types. This avoids value copy to create
+  // MapEntryLite from google::protobuf::Map in serialization.
+  static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
+    return Arena::Create<MapEntryWrapper<Key, Value, kKeyFieldType,
+                                         kValueFieldType, default_enum_value> >(
+        arena, key, value, arena);
+  }
+
+ protected:
+  void set_has_key() { _has_bits_[0] |= 0x00000001u; }
+  bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
+  void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
+  void set_has_value() { _has_bits_[0] |= 0x00000002u; }
+  bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
+  void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+
+ private:
+  // Serializing a generated message containing map field involves serializing
+  // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
+  // after serialization should be the same as that of a MapEntry message
+  // containing the same key and value inside it.  However, google::protobuf::Map doesn't
+  // store key and value as MapEntry message, which disables us to use existing
+  // code to serialize message. In order to use existing code to serialize
+  // message, we need to construct a MapEntry from key-value pair. But it
+  // involves copy of key and value to construct a MapEntry. In order to avoid
+  // this copy in constructing a MapEntry, we need the following class which
+  // only takes references of given key and value.
+  template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+            WireFormatLite::FieldType v_wire_type, int default_enum>
+  class LIBPROTOBUF_EXPORT MapEntryWrapper
+      : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+    typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+    typedef typename Base::KeyCppType KeyCppType;
+    typedef typename Base::ValCppType ValCppType;
+
+   public:
+    MapEntryWrapper(const K& key, const V& value, Arena* arena)
+        : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+          key_(key),
+          value_(value) {
+      Base::set_has_key();
+      Base::set_has_value();
+    }
+    inline const KeyCppType& key() const { return key_; }
+    inline const ValCppType& value() const { return value_; }
+
+   private:
+    const Key& key_;
+    const Value& value_;
+
+    friend class ::google::protobuf::Arena;
+    typedef void DestructorSkippable_;
+  };
+
+  // Like above, but for enum value only, which stores value instead of
+  // reference of value field inside. This is needed because the type of value
+  // field in constructor is an enum, while we need to store it as an int. If we
+  // initialize a reference to int with a reference to enum, compiler will
+  // generate a temporary int from enum and initialize the reference to int with
+  // the temporary.
+  template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+            WireFormatLite::FieldType v_wire_type, int default_enum>
+  class LIBPROTOBUF_EXPORT MapEnumEntryWrapper
+      : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+    typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+    typedef typename Base::KeyCppType KeyCppType;
+    typedef typename Base::ValCppType ValCppType;
+
+   public:
+    MapEnumEntryWrapper(const K& key, const V& value, Arena* arena)
+        : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+          key_(key),
+          value_(value) {
+      Base::set_has_key();
+      Base::set_has_value();
+    }
+    inline const KeyCppType& key() const { return key_; }
+    inline const ValCppType& value() const { return value_; }
+
+   private:
+    const KeyCppType& key_;
+    const ValCppType value_;
+
+    friend class ::google::protobuf::Arena;
+    typedef void DestructorSkippable_;
+  };
+
+  MapEntryLite() : default_instance_(NULL), arena_(NULL) {
+    KeyCppHandler::Initialize(&key_, NULL);
+    ValueCppHandler::InitializeMaybeByDefaultEnum(
+        &value_, default_enum_value, NULL);
+    _has_bits_[0] = 0;
+  }
+
+  explicit MapEntryLite(Arena* arena)
+      : default_instance_(NULL), arena_(arena) {
+    KeyCppHandler::Initialize(&key_, arena);
+    ValueCppHandler::InitializeMaybeByDefaultEnum(
+        &value_, default_enum_value, arena);
+    _has_bits_[0] = 0;
+  }
+
+  inline Arena* GetArenaNoVirtual() const {
+    return arena_;
+  }
+
+  void set_default_instance(MapEntryLite* default_instance) {
+    default_instance_ = default_instance;
+  }
+
+  MapEntryLite* default_instance_;
+
+  KeyBase key_;
+  ValueBase value_;
+  Arena* arena_;
+  uint32 _has_bits_[1];
+
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  template <typename K, typename V, WireFormatLite::FieldType,
+            WireFormatLite::FieldType, int>
+  friend class LIBPROTOBUF_EXPORT internal::MapEntry;
+  template <typename K, typename V, WireFormatLite::FieldType,
+            WireFormatLite::FieldType, int>
+  friend class LIBPROTOBUF_EXPORT internal::MapFieldLite;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index b535ec2..fd40c0d 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -55,14 +55,14 @@
 }
 
 void RegisterMapEntryDefaultInstance(MessageLite* default_instance) {
-  GoogleOnceInit(&map_entry_default_instances_once_,
+  ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_,
                  &InitMapEntryDefaultInstances);
   MutexLock lock(map_entry_default_instances_mutex_);
   map_entry_default_instances_->push_back(default_instance);
 }
 
 MapFieldBase::~MapFieldBase() {
-  if (repeated_field_ != NULL) delete repeated_field_;
+  if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
 }
 
 const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
@@ -118,7 +118,9 @@
 }
 
 void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
-  if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField<Message>;
+  if (repeated_field_ == NULL) {
+    repeated_field_ = Arena::Create<RepeatedPtrField<Message> >(arena_, arena_);
+  }
 }
 
 void MapFieldBase::SyncMapWithRepeatedField() const {
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 8516d74..6d8b6ec 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -34,8 +34,10 @@
 #include <google/protobuf/stubs/atomicops.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/map.h>
+#include <google/protobuf/arena.h>
 #include <google/protobuf/map_entry.h>
+#include <google/protobuf/map_field_lite.h>
+#include <google/protobuf/map_type_handler.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/unknown_field_set.h>
@@ -56,7 +58,13 @@
 class LIBPROTOBUF_EXPORT MapFieldBase {
  public:
   MapFieldBase()
-      : base_map_(NULL),
+      : arena_(NULL),
+        repeated_field_(NULL),
+        entry_descriptor_(NULL),
+        assign_descriptor_callback_(NULL),
+        state_(STATE_MODIFIED_MAP) {}
+  explicit MapFieldBase(Arena* arena)
+      : arena_(arena),
         repeated_field_(NULL),
         entry_descriptor_(NULL),
         assign_descriptor_callback_(NULL),
@@ -109,7 +117,7 @@
     CLEAN = 2,  // data in map and repeated field are same
   };
 
-  mutable void* base_map_;
+  Arena* arena_;
   mutable RepeatedPtrField<Message>* repeated_field_;
   // MapEntry can only be created from MapField. To create MapEntry, MapField
   // needs to know its descriptor, because MapEntry is not generated class which
@@ -134,41 +142,55 @@
 // This class provides accesss to map field using generated api. It is used for
 // internal generated message implentation only. Users should never use this
 // directly.
-template<typename Key, typename T,
-         FieldDescriptor::Type KeyProto,
-         FieldDescriptor::Type ValueProto, int default_enum_value = 0>
-class MapField : public MapFieldBase {
-  // Handlers for key/value's proto field type.
-  typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler;
-  typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler;
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value = 0>
+class LIBPROTOBUF_EXPORT MapField : public MapFieldBase,
+                 public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+                                     default_enum_value> {
+  // Handlers for key/value wire type. Provide utilities to parse/serialize
+  // key/value.
+  typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+  typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
 
   // Define key/value's internal stored type.
-  typedef typename KeyProtoHandler::CppType KeyHandlerCpp;
-  typedef typename ValueProtoHandler::CppType ValHandlerCpp;
-  static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
-  static const bool kIsValMessage = ValueProtoHandler::kIsMessage;
-  typedef typename MapIf<kIsKeyMessage, Key, KeyHandlerCpp>::type KeyCpp;
-  typedef typename MapIf<kIsValMessage, T  , ValHandlerCpp>::type ValCpp;
+  static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+  static const bool kIsValMessage = ValueWireHandler::kIsMessage;
+  typedef typename KeyWireHandler::CppType KeyInternalType;
+  typedef typename ValueWireHandler::CppType ValueInternalType;
+  typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp;
+  typedef typename MapIf<kIsValMessage, T  , ValueInternalType>::type ValCpp;
 
   // Handlers for key/value's internal stored type.
   typedef MapCppTypeHandler<KeyCpp> KeyHandler;
   typedef MapCppTypeHandler<ValCpp> ValHandler;
 
   // Define message type for internal repeated field.
-  typedef MapEntry<Key, T, KeyProto, ValueProto, default_enum_value> EntryType;
+  typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
+      EntryType;
+  typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType,
+                       default_enum_value> EntryLiteType;
+
+  // Define abbreviation for parent MapFieldLite
+  typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+                       default_enum_value> MapFieldLiteType;
 
   // Enum needs to be handled differently from other types because it has
   // different exposed type in google::protobuf::Map's api and repeated field's api. For
   // details see the comment in the implementation of
   // SyncMapWithRepeatedFieldNoLocki.
-  static const bool kIsValueEnum = ValueProtoHandler::kIsEnum;
+  static const bool kIsValueEnum = ValueWireHandler::kIsEnum;
   typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
 
  public:
   MapField();
+  explicit MapField(Arena* arena);
   // MapField doesn't own the default_entry, which means default_entry must
   // outlive the lifetime of MapField.
   MapField(const Message* default_entry);
+  // For tests only.
+  MapField(Arena* arena, const Message* default_entry);
   ~MapField();
 
   // Accessors
@@ -178,29 +200,22 @@
   // Convenient methods for generated message implementation.
   int size() const;
   void Clear();
-  void MergeFrom(const MapField& other);
-  void Swap(MapField* other);
+  void MergeFrom(const MapFieldLiteType& other);
+  void Swap(MapFieldLiteType* other);
 
   // Allocates metadata only if this MapField is part of a generated message.
   void SetEntryDescriptor(const Descriptor** descriptor);
   void SetAssignDescriptorCallback(void (*callback)());
 
-  // Set default enum value only for proto2 map field whose value is enum type.
-  void SetDefaultEnumValue();
-
-  // Used in the implementation of parsing. Caller should take the ownership.
-  EntryType* NewEntry() const;
-  // Used in the implementation of serializing enum value type. Caller should
-  // take the ownership.
-  EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
-  // Used in the implementation of serializing other value types. Caller should
-  // take the ownership.
-  EntryType* NewEntryWrapper(const Key& key, const T& t) const;
-
  private:
+  typedef void DestructorSkippable_;
+
   // MapField needs MapEntry's default instance to create new MapEntry.
   void InitDefaultEntryOnce() const;
 
+  // Manually set default entry instance. For test only.
+  void SetDefaultEntryOnce(const EntryType* default_entry) const;
+
   // Convenient methods to get internal google::protobuf::Map
   const Map<Key, T>& GetInternalMap() const;
   Map<Key, T>* MutableInternalMap();
@@ -211,14 +226,9 @@
   int SpaceUsedExcludingSelfNoLock() const;
 
   mutable const EntryType* default_entry_;
-};
 
-// True if IsInitialized() is true for value field in all elements of t. T is
-// expected to be message.  It's useful to have this helper here to keep the
-// protobuf compiler from ever having to emit loops in IsInitialized() methods.
-// We want the C++ compiler to inline this or not as it sees fit.
-template <typename Key, typename T>
-bool AllAreInitialized(const Map<Key, T>& t);
+  friend class ::google::protobuf::Arena;
+};
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 79302e4..ae63c72 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -43,160 +43,183 @@
 namespace protobuf {
 namespace internal {
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField()
-    : default_entry_(NULL) {
-  MapFieldBase::base_map_ = new Map<Key, T>;
-  SetDefaultEnumValue();
-}
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField()
+    : default_entry_(NULL) {}
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField(
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+    Arena* arena)
+    : MapFieldBase(arena),
+      MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+          arena),
+      default_entry_(NULL) {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
     const Message* default_entry)
-    : default_entry_(down_cast<const EntryType*>(default_entry)) {
-  MapFieldBase::base_map_ = new Map<Key, T>;
-  SetDefaultEnumValue();
-}
+    : default_entry_(down_cast<const EntryType*>(default_entry)) {}
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::~MapField() {
-  delete reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
-}
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+    Arena* arena, const Message* default_entry)
+    : MapFieldBase(arena),
+      MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+          arena),
+      default_entry_(down_cast<const EntryType*>(default_entry)) {}
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-int MapField<Key, T, KeyProto, ValueProto, default_enum_value>::size() const {
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::~MapField() {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::size() const {
   SyncMapWithRepeatedField();
-  return GetInternalMap().size();
+  return MapFieldLiteType::GetInternalMap().size();
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Clear() {
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::Clear() {
   SyncMapWithRepeatedField();
-  MutableInternalMap()->clear();
+  MapFieldLiteType::MutableInternalMap()->clear();
   SetMapDirty();
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
 const Map<Key, T>&
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::GetMap() const {
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::GetMap() const {
   SyncMapWithRepeatedField();
-  return GetInternalMap();
+  return MapFieldLiteType::GetInternalMap();
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
 Map<Key, T>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MutableMap() {
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::MutableMap() {
   SyncMapWithRepeatedField();
-  Map<Key, T>* result = MutableInternalMap();
+  Map<Key, T>* result = MapFieldLiteType::MutableInternalMap();
   SetMapDirty();
   return result;
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MergeFrom(
-    const MapField& other) {
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::MergeFrom(
+    const MapFieldLiteType& other) {
+  const MapField& down_other = down_cast<const MapField&>(other);
   SyncMapWithRepeatedField();
-  other.SyncMapWithRepeatedField();
-
-  Map<Key, T>* map = MutableInternalMap();
-  const Map<Key, T>& other_map = other.GetInternalMap();
-  for (typename Map<Key, T>::const_iterator it = other_map.begin();
-       it != other_map.end(); ++it) {
-    (*map)[it->first] = it->second;
-  }
+  down_other.SyncMapWithRepeatedField();
+  MapFieldLiteType::MergeFrom(other);
   SetMapDirty();
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Swap(
-    MapField* other) {
-  std::swap(repeated_field_, other->repeated_field_);
-  std::swap(base_map_, other->base_map_);
-  std::swap(state_, other->state_);
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::Swap(
+    MapFieldLiteType* other) {
+  MapField* down_other = down_cast<MapField*>(other);
+  std::swap(repeated_field_, down_other->repeated_field_);
+  MapFieldLiteType::Swap(other);
+  std::swap(state_, down_other->state_);
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
 void
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::SetEntryDescriptor(
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SetEntryDescriptor(
     const Descriptor** descriptor) {
   entry_descriptor_ = descriptor;
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
 void
-MapField<Key, T, KeyProto, ValueProto,
+MapField<Key, T, kKeyFieldType, kValueFieldType,
          default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
   assign_descriptor_callback_ = callback;
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
-              default_enum_value>::SetDefaultEnumValue() {
-  MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+const Map<Key, T>&
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::GetInternalMap() const {
+  return MapFieldLiteType::GetInternalMap();
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntry() const {
-  // The MapEntry instance created here is only used in generated code for
-  // parsing. It doesn't have default instance, descriptor or reflection,
-  // because these are not needed in parsing and will prevent us from using it
-  // for parsing MessageLite.
-  return new EntryType();
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+Map<Key, T>*
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::MutableInternalMap() {
+  return MapFieldLiteType::MutableInternalMap();
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntryWrapper(
-    const Key& key, const T& t) const {
-  return EntryType::Wrap(key, t);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEnumEntryWrapper(
-    const Key& key, const T t) const {
-  return EntryType::EnumWrap(key, t);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-const Map<Key, T>& MapField<Key, T, KeyProto, ValueProto,
-                            default_enum_value>::GetInternalMap() const {
-  return *reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-Map<Key, T>* MapField<Key, T, KeyProto, ValueProto,
-                      default_enum_value>::MutableInternalMap() {
-  return reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
-              default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
   if (repeated_field_ == NULL) {
-    repeated_field_ = new RepeatedPtrField<Message>();
+    if (arena_ == NULL) {
+      repeated_field_ = new RepeatedPtrField<Message>();
+    } else {
+      repeated_field_ =
+          Arena::Create<RepeatedPtrField<Message> >(arena_, arena_);
+    }
   }
-  const Map<Key, T>& map =
-      *static_cast<const Map<Key, T>*>(MapFieldBase::base_map_);
+  const Map<Key, T>& map = GetInternalMap();
   RepeatedPtrField<EntryType>* repeated_field =
       reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
 
@@ -206,18 +229,21 @@
        it != map.end(); ++it) {
     InitDefaultEntryOnce();
     GOOGLE_CHECK(default_entry_ != NULL);
-    EntryType* new_entry = down_cast<EntryType*>(default_entry_->New());
+    EntryType* new_entry = down_cast<EntryType*>(default_entry_->New(arena_));
     repeated_field->AddAllocated(new_entry);
-    new_entry->set_key(it->first);
-    new_entry->set_value(it->second);
+    (*new_entry->mutable_key()) = it->first;
+    (*new_entry->mutable_value()) = it->second;
   }
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
-              default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
-  Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
+  Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
   RepeatedPtrField<EntryType>* repeated_field =
       reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
   map->clear();
@@ -232,15 +258,18 @@
   }
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-int MapField<Key, T, KeyProto, ValueProto,
-             default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
   int size = 0;
   if (repeated_field_ != NULL) {
     size += repeated_field_->SpaceUsedExcludingSelf();
   }
-  Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+  Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
   size += sizeof(*map);
   for (typename Map<Key, T>::iterator it = map->begin();
        it != map->end(); ++it) {
@@ -250,10 +279,14 @@
   return size;
 }
 
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
-          FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
-              default_enum_value>::InitDefaultEntryOnce() const {
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::InitDefaultEntryOnce()
+    const {
   if (default_entry_ == NULL) {
     InitMetadataOnce();
     GOOGLE_CHECK(*entry_descriptor_ != NULL);
@@ -262,15 +295,6 @@
   }
 }
 
-template <typename Key, typename T>
-bool AllAreInitialized(const Map<Key, T>& t) {
-  for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
-       ++it) {
-    if (!it->second.IsInitialized()) return false;
-  }
-  return true;
-}
-
 }  // namespace internal
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
new file mode 100644
index 0000000..549ecc0
--- /dev/null
+++ b/src/google/protobuf/map_field_lite.h
@@ -0,0 +1,278 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_entry_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This class provides accesss to map field using generated api. It is used for
+// internal generated message implentation only. Users should never use this
+// directly.
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value = 0>
+class LIBPROTOBUF_EXPORT MapFieldLite {
+  // Define message type for internal repeated field.
+  typedef MapEntryLite<Key, T, key_wire_type, value_wire_type,
+                       default_enum_value> EntryType;
+
+ public:
+  MapFieldLite();
+  explicit MapFieldLite(Arena* arena);
+  virtual ~MapFieldLite();
+
+  // Accessors
+  virtual const Map<Key, T>& GetMap() const;
+  virtual Map<Key, T>* MutableMap();
+
+  // Convenient methods for generated message implementation.
+  virtual int size() const;
+  virtual void Clear();
+  virtual void MergeFrom(const MapFieldLite& other);
+  virtual void Swap(MapFieldLite* other);
+
+  // Set default enum value only for proto2 map field whose value is enum type.
+  void SetDefaultEnumValue();
+
+  // Used in the implementation of parsing. Caller should take the ownership.
+  EntryType* NewEntry() const;
+  // Used in the implementation of serializing enum value type. Caller should
+  // take the ownership.
+  EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
+  // Used in the implementation of serializing other value types. Caller should
+  // take the ownership.
+  EntryType* NewEntryWrapper(const Key& key, const T& t) const;
+
+ protected:
+  // Convenient methods to get internal google::protobuf::Map
+  virtual const Map<Key, T>& GetInternalMap() const;
+  virtual Map<Key, T>* MutableInternalMap();
+
+ private:
+  typedef void DestructorSkippable_;
+
+  Arena* arena_;
+  Map<Key, T>* map_;
+
+  friend class ::google::protobuf::Arena;
+};
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MapFieldLite()
+    : arena_(NULL) {
+  map_ = new Map<Key, T>;
+  SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MapFieldLite(Arena* arena)
+  : arena_(arena) {
+  map_ = Arena::Create<Map<Key, T> >(arena, arena);
+  SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::~MapFieldLite() {
+  delete map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::GetMap() const {
+  return *map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MutableMap() {
+  return map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+int
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::size() const {
+  return map_->size();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::Clear() {
+  map_->clear();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MergeFrom(
+    const MapFieldLite& other) {
+  for (typename Map<Key, T>::const_iterator it = other.map_->begin();
+       it != other.map_->end(); ++it) {
+    (*map_)[it->first] = it->second;
+  }
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::Swap(
+    MapFieldLite* other) {
+  std::swap(map_, other->map_);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::SetDefaultEnumValue() {
+  MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::GetInternalMap() const {
+  return *map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MutableInternalMap() {
+  return map_;
+}
+
+#define EntryType \
+  MapEntryLite<Key, T, key_wire_type, value_wire_type, default_enum_value>
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::NewEntry() const {
+  if (arena_ == NULL) {
+    return new EntryType();
+  } else {
+    return Arena::CreateMessage<EntryType>(arena_);
+  }
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::NewEnumEntryWrapper(const Key& key,
+                                                      const T t) const {
+  return EntryType::EnumWrap(key, t, arena_);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::NewEntryWrapper(const Key& key,
+                                                  const T& t) const {
+  return EntryType::Wrap(key, t, arena_);
+}
+
+#undef EntryType
+
+// True if IsInitialized() is true for value field in all elements of t. T is
+// expected to be message.  It's useful to have this helper here to keep the
+// protobuf compiler from ever having to emit loops in IsInitialized() methods.
+// We want the C++ compiler to inline this or not as it sees fit.
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t) {
+  for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
+       ++it) {
+    if (!it->second.IsInitialized()) return false;
+  }
+  return true;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 045f8f2..61344cb 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -35,13 +35,16 @@
 #endif
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
 #include <google/protobuf/map.h>
+#include <google/protobuf/arena_test_util.h>
 #include <google/protobuf/map_unittest.pb.h>
 #include <google/protobuf/map_test_util.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/map_field_inl.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 #include <gtest/gtest.h>
 
 namespace google {
@@ -53,6 +56,9 @@
 
 class MapFieldBaseStub : public MapFieldBase {
  public:
+  typedef void DestructorSkippable_;
+  MapFieldBaseStub() {}
+  explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
   void SyncRepeatedFieldWithMap() const {
     MapFieldBase::SyncRepeatedFieldWithMap();
   }
@@ -63,16 +69,6 @@
   RepeatedPtrField<Message>* InternalRepeatedField() {
     return repeated_field_;
   }
-  // Get underlined map without synchronizing repeated field.
-  template <typename MapType>
-  const MapType& GetMap() {
-    return *reinterpret_cast<MapType*>(base_map_);
-  }
-  // Get underlined map without synchronizing repeated field.
-  template <typename MapType>
-  MapType* MutableMap() {
-    return reinterpret_cast<MapType*>(base_map_);
-  }
   bool IsMapClean() { return state_ != 0; }
   bool IsRepeatedClean() { return state_ != 1; }
   void SetMapDirty() { state_ = 0; }
@@ -81,8 +77,8 @@
 
 class MapFieldBasePrimitiveTest : public ::testing::Test {
  protected:
-  typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
-                   FieldDescriptor::TYPE_INT32> MapFieldType;
+  typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+                   WireFormatLite::TYPE_INT32, false> MapFieldType;
 
   MapFieldBasePrimitiveTest() {
     // Get descriptors
@@ -144,6 +140,38 @@
   }
 }
 
+TEST_F(MapFieldBasePrimitiveTest, Arena) {
+  // Allocate a large initial block to avoid mallocs during hooked test.
+  std::vector<char> arena_block(128 * 1024);
+  ArenaOptions options;
+  options.initial_block = arena_block.data();
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+
+  {
+    NoHeapChecker no_heap;
+
+    MapFieldType* map_field =
+        Arena::Create<MapFieldType>(&arena, &arena, default_entry_);
+
+    // Set content in map
+    (*map_field->MutableMap())[100] = 101;
+
+    // Trigger conversion to repeated field.
+    map_field->GetRepeatedField();
+  }
+
+  {
+    NoHeapChecker no_heap;
+
+    MapFieldBaseStub* map_field =
+        Arena::Create<MapFieldBaseStub>(&arena, &arena);
+
+    // Trigger conversion to repeated field.
+    EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
+  }
+}
+
 namespace {
 enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
 }  // anonymous namespace
@@ -152,8 +180,10 @@
     : public testing::TestWithParam<State> {
  public:
  protected:
-  typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
-                FieldDescriptor::TYPE_INT32> MapFieldType;
+  typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+                   WireFormatLite::TYPE_INT32, false> MapFieldType;
+  typedef MapFieldLite<int32, int32, WireFormatLite::TYPE_INT32,
+                       WireFormatLite::TYPE_INT32, false> MapFieldLiteType;
   MapFieldStateTest() : state_(GetParam()) {
     // Build map field
     const Descriptor* map_descriptor =
@@ -199,9 +229,8 @@
     MakeMapDirty(map_field);
     MapFieldBase* map_field_base = map_field;
     map_field_base->MutableRepeatedField();
-    MapFieldBaseStub* stub =
-        reinterpret_cast<MapFieldBaseStub*>(map_field_base);
-    Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+    Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+                                 ->MapFieldLiteType::MutableMap();
     map->clear();
 
     Expect(map_field, REPEATED_DIRTY, 0, 1, false);
@@ -213,7 +242,8 @@
     MapFieldBaseStub* stub =
         reinterpret_cast<MapFieldBaseStub*>(map_field_base);
 
-    Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+    Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+                                 ->MapFieldLiteType::MutableMap();
     RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
 
     switch (state) {
@@ -430,6 +460,7 @@
   }
 }
 
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc
new file mode 100644
index 0000000..b65b4d6
--- /dev/null
+++ b/src/google/protobuf/map_lite_test_util.cc
@@ -0,0 +1,93 @@
+// 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 <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_test_util_impl.h>
+
+namespace google {
+namespace protobuf {
+
+void MapLiteTestUtil::SetMapFields(unittest::TestMapLite* message) {
+  MapTestUtilImpl::SetMapFields<unittest::MapEnumLite,
+                                unittest::MAP_ENUM_BAR_LITE,
+                                unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetArenaMapFields(unittest::TestArenaMapLite* message) {
+  MapTestUtilImpl::SetArenaMapFields<unittest::MapEnumLite,
+                                     unittest::MAP_ENUM_BAR_LITE,
+                                     unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetMapFieldsInitialized(unittest::TestMapLite* message) {
+  MapTestUtilImpl::SetMapFieldsInitialized(message);
+}
+
+void MapLiteTestUtil::ModifyMapFields(unittest::TestMapLite* message) {
+  MapTestUtilImpl::ModifyMapFields<unittest::MapEnumLite,
+                                   unittest::MAP_ENUM_FOO_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectClear(const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectClear(message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSet(const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnumLite,
+                                      unittest::MAP_ENUM_BAR_LITE,
+                                      unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectArenaMapFieldsSet(
+    const unittest::TestArenaMapLite& message) {
+  MapTestUtilImpl::ExpectArenaMapFieldsSet<unittest::MapEnumLite,
+                                           unittest::MAP_ENUM_BAR_LITE,
+                                           unittest::MAP_ENUM_BAZ_LITE>(
+      message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSetInitialized(
+    const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnumLite,
+                                                 unittest::MAP_ENUM_FOO_LITE>(
+      message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsModified(
+    const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectMapFieldsModified<unittest::MapEnumLite,
+                                           unittest::MAP_ENUM_BAR_LITE,
+                                           unittest::MAP_ENUM_FOO_LITE>(
+      message);
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h
new file mode 100644
index 0000000..77b5336
--- /dev/null
+++ b/src/google/protobuf/map_lite_test_util.h
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
+
+#include <google/protobuf/map_lite_unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+class MapLiteTestUtil {
+ public:
+  // Set every field in the TestMapLite message to a unique value.
+  static void SetMapFields(protobuf_unittest::TestMapLite* message);
+
+  // Set every field in the TestArenaMapLite message to a unique value.
+  static void SetArenaMapFields(protobuf_unittest::TestArenaMapLite* message);
+
+  // Set every field in the message to a default value.
+  static void SetMapFieldsInitialized(protobuf_unittest::TestMapLite* message);
+
+  // Modify all the map fields of the messsage (which should already have been
+  // initialized with SetMapFields()).
+  static void ModifyMapFields(protobuf_unittest::TestMapLite* message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called.
+  static void ExpectMapFieldsSet(const protobuf_unittest::TestMapLite& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called for TestArenaMapLite.
+  static void ExpectArenaMapFieldsSet(
+      const protobuf_unittest::TestArenaMapLite& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFieldsInitialized() is called.
+  static void ExpectMapFieldsSetInitialized(
+      const protobuf_unittest::TestMapLite& message);
+
+  // Expect that the message is modified as would be expected from
+  // ModifyMapFields().
+  static void ExpectMapFieldsModified(
+      const protobuf_unittest::TestMapLite& message);
+
+  // Check that all fields are empty.
+  static void ExpectClear(const protobuf_unittest::TestMapLite& message);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
index cc71555..c69e8d9 100644
--- a/src/google/protobuf/map_lite_unittest.proto
+++ b/src/google/protobuf/map_lite_unittest.proto
@@ -30,10 +30,104 @@
 
 syntax = "proto2";
 
+option cc_enable_arenas = true;
 option optimize_for = LITE_RUNTIME;
 
+import "google/protobuf/unittest_lite.proto";
+
 package protobuf_unittest;
 
-message MapLite {
-  map<int32, int32> map_field = 1;
+message TestMapLite {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnumLite> map_int32_enum     = 16;
+  map<int32   , ForeignMessageLite> map_int32_foreign_message = 17;
+  map<int32, int32> teboring = 18;
+}
+
+message TestArenaMapLite {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<int32   , MapEnumLite> map_int32_enum     = 14;
+  map<int32   , ForeignMessageArenaLite> map_int32_foreign_message = 15;
+}
+
+// Test embeded message with required fields
+message TestRequiredMessageMapLite {
+  map<int32, TestRequiredLite> map_field = 1;
+}
+
+message TestEnumStartWithNonZeroMapLite {
+  map<int32, Proto2MapEnumStartWithNonZeroLite> map_field = 101;
+}
+
+message TestEnumMapLite {
+  map<int32, Proto2MapEnumLite> known_map_field = 101;
+  map<int32, Proto2MapEnumLite> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtraLite {
+  map<int32, Proto2MapEnumPlusExtraLite> known_map_field = 101;
+  map<int32, Proto2MapEnumPlusExtraLite> unknown_map_field = 102;
+}
+
+message TestMessageMapLite {
+  map<int32, TestAllTypesLite> map_int32_message = 1;
+}
+
+enum Proto2MapEnumLite {
+  PROTO2_MAP_ENUM_FOO_LITE = 0;
+  PROTO2_MAP_ENUM_BAR_LITE = 1;
+  PROTO2_MAP_ENUM_BAZ_LITE = 2;
+}
+
+enum Proto2MapEnumPlusExtraLite {
+  E_PROTO2_MAP_ENUM_FOO_LITE   = 0;
+  E_PROTO2_MAP_ENUM_BAR_LITE   = 1;
+  E_PROTO2_MAP_ENUM_BAZ_LITE   = 2;
+  E_PROTO2_MAP_ENUM_EXTRA_LITE = 3;
+}
+
+enum Proto2MapEnumStartWithNonZeroLite {
+  PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE = 1;
+}
+
+enum MapEnumLite {
+  MAP_ENUM_FOO_LITE = 0;
+  MAP_ENUM_BAR_LITE = 1;
+  MAP_ENUM_BAZ_LITE = 2;
+}
+
+message TestRequiredLite {
+  required int32 a = 1;
+  required int32 b = 2;
+  required int32 c = 3;
+}
+
+message ForeignMessageArenaLite {
+  optional int32 c = 1;
 }
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 9db6752..88cba1f 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -39,7 +39,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/testing/file.h>
-#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/arena_test_util.h>
 #include <google/protobuf/map_proto2_unittest.pb.h>
 #include <google/protobuf/map_unittest.pb.h>
 #include <google/protobuf/map_test_util.h>
@@ -191,6 +191,7 @@
 }
 
 #ifdef PROTOBUF_HAS_DEATH_TEST
+
 TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
   EXPECT_DEATH(map_.at(0), "");
 }
@@ -198,6 +199,7 @@
 TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
   EXPECT_DEATH(const_map_.at(0), "");
 }
+
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
 TEST_F(MapImplTest, CountNonExist) {
@@ -553,6 +555,14 @@
   EXPECT_EQ(101, std_map[100]);
 }
 
+TEST_F(MapImplTest, ConvertToStdVectorOfPairs) {
+  map_[100] = 101;
+  std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end());
+  EXPECT_EQ(1, std_vec.size());
+  EXPECT_EQ(100, std_vec[0].first);
+  EXPECT_EQ(101, std_vec[0].second);
+}
+
 // Map Field Reflection Test ========================================
 
 static int Func(int i, int j) {
@@ -1717,6 +1727,20 @@
   EXPECT_EQ(0, message.map_int32_int32().at(1));
 }
 
+TEST(GeneratedMapFieldTest, MissedValueTextFormat) {
+  unittest::TestMap message;
+
+  // No value field in text format
+  string text =
+      "map_int32_foreign_message {\n"
+      "  key: 1234567890\n"
+      "}";
+
+  EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message));
+  EXPECT_EQ(1, message.map_int32_foreign_message().size());
+  EXPECT_EQ(11, message.ByteSize());
+}
+
 TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) {
   unittest::TestMap message;
 
@@ -1737,18 +1761,6 @@
   EXPECT_FALSE(message.ParseFromString(data));
 }
 
-TEST(GeneratedMapFieldTest, MessageLiteMap) {
-  unittest::MapLite from, to;
-  (*from.mutable_map_field())[1] = 1;
-
-  string data;
-  from.SerializeToString(&data);
-  to.ParseFromString(data);
-
-  EXPECT_EQ(1, to.map_field().size());
-  EXPECT_EQ(1, to.map_field().at(1));
-}
-
 TEST(GeneratedMapFieldTest, IsInitialized) {
   unittest::TestRequiredMessageMap map_message;
 
@@ -2247,6 +2259,52 @@
 }
 
 
+// arena support =================================================
+TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
+  // Allocate a large initial block to avoid mallocs during hooked test.
+  std::vector<char> arena_block(128 * 1024);
+  ArenaOptions options;
+  options.initial_block = arena_block.data();
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+  string data;
+  data.reserve(128 * 1024);
+
+  {
+    NoHeapChecker no_heap;
+
+    unittest::TestArenaMap* from =
+        Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+    MapTestUtil::SetArenaMapFields(from);
+    from->SerializeToString(&data);
+
+    unittest::TestArenaMap* to =
+        Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+    to->ParseFromString(data);
+    MapTestUtil::ExpectArenaMapFieldsSet(*to);
+  }
+}
+
+// Use text format parsing and serializing to test reflection api.
+TEST(ArenaTest, RelfectionInTextFormat) {
+  Arena arena;
+  string data;
+
+  TextFormat::Printer printer;
+  TextFormat::Parser parser;
+
+  unittest::TestArenaMap* from =
+      Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+  unittest::TestArenaMap* to =
+      Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+
+  MapTestUtil::SetArenaMapFields(from);
+  printer.PrintToString(*from, &data);
+
+  EXPECT_TRUE(parser.ParseFromString(data, to));
+  MapTestUtil::ExpectArenaMapFieldsSet(*to);
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
index eb7ea51..1713e37 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -29,275 +29,60 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <google/protobuf/map_test_util.h>
+#include <google/protobuf/map_test_util_impl.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/message.h>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
 namespace google {
 namespace protobuf {
 
 void MapTestUtil::SetMapFields(unittest::TestMap* message) {
-  // Add first element.
-  (*message->mutable_map_int32_int32())[0] = 0;
-  (*message->mutable_map_int64_int64())[0] = 0;
-  (*message->mutable_map_uint32_uint32())[0] = 0;
-  (*message->mutable_map_uint64_uint64())[0] = 0;
-  (*message->mutable_map_sint32_sint32())[0] = 0;
-  (*message->mutable_map_sint64_sint64())[0] = 0;
-  (*message->mutable_map_fixed32_fixed32())[0] = 0;
-  (*message->mutable_map_fixed64_fixed64())[0] = 0;
-  (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
-  (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
-  (*message->mutable_map_int32_float())[0] = 0.0;
-  (*message->mutable_map_int32_double())[0] = 0.0;
-  (*message->mutable_map_bool_bool())[0] = false;
-  (*message->mutable_map_string_string())["0"] = "0";
-  (*message->mutable_map_int32_bytes())[0] = "0";
-  (*message->mutable_map_int32_enum())[0] =
-      unittest::MAP_ENUM_BAR;
-  (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+  MapTestUtilImpl::SetMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+                                unittest::MAP_ENUM_BAZ>(message);
+}
 
-  // Add second element
-  (*message->mutable_map_int32_int32())[1] = 1;
-  (*message->mutable_map_int64_int64())[1] = 1;
-  (*message->mutable_map_uint32_uint32())[1] = 1;
-  (*message->mutable_map_uint64_uint64())[1] = 1;
-  (*message->mutable_map_sint32_sint32())[1] = 1;
-  (*message->mutable_map_sint64_sint64())[1] = 1;
-  (*message->mutable_map_fixed32_fixed32())[1] = 1;
-  (*message->mutable_map_fixed64_fixed64())[1] = 1;
-  (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
-  (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
-  (*message->mutable_map_int32_float())[1] = 1.0;
-  (*message->mutable_map_int32_double())[1] = 1.0;
-  (*message->mutable_map_bool_bool())[1] = true;
-  (*message->mutable_map_string_string())["1"] = "1";
-  (*message->mutable_map_int32_bytes())[1] = "1";
-  (*message->mutable_map_int32_enum())[1] =
-      unittest::MAP_ENUM_BAZ;
-  (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) {
+  MapTestUtilImpl::SetArenaMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+                                     unittest::MAP_ENUM_BAZ>(message);
 }
 
 void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) {
-  // Add first element using bracket operator, which should assign default
-  // value automatically.
-  (*message->mutable_map_int32_int32())[0];
-  (*message->mutable_map_int64_int64())[0];
-  (*message->mutable_map_uint32_uint32())[0];
-  (*message->mutable_map_uint64_uint64())[0];
-  (*message->mutable_map_sint32_sint32())[0];
-  (*message->mutable_map_sint64_sint64())[0];
-  (*message->mutable_map_fixed32_fixed32())[0];
-  (*message->mutable_map_fixed64_fixed64())[0];
-  (*message->mutable_map_sfixed32_sfixed32())[0];
-  (*message->mutable_map_sfixed64_sfixed64())[0];
-  (*message->mutable_map_int32_float())[0];
-  (*message->mutable_map_int32_double())[0];
-  (*message->mutable_map_bool_bool())[0];
-  (*message->mutable_map_string_string())["0"];
-  (*message->mutable_map_int32_bytes())[0];
-  (*message->mutable_map_int32_enum())[0];
-  (*message->mutable_map_int32_foreign_message())[0];
+  MapTestUtilImpl::SetMapFieldsInitialized(message);
 }
 
 void MapTestUtil::ModifyMapFields(unittest::TestMap* message) {
-  (*message->mutable_map_int32_int32())[1] = 2;
-  (*message->mutable_map_int64_int64())[1] = 2;
-  (*message->mutable_map_uint32_uint32())[1] = 2;
-  (*message->mutable_map_uint64_uint64())[1] = 2;
-  (*message->mutable_map_sint32_sint32())[1] = 2;
-  (*message->mutable_map_sint64_sint64())[1] = 2;
-  (*message->mutable_map_fixed32_fixed32())[1] = 2;
-  (*message->mutable_map_fixed64_fixed64())[1] = 2;
-  (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
-  (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
-  (*message->mutable_map_int32_float())[1] = 2.0;
-  (*message->mutable_map_int32_double())[1] = 2.0;
-  (*message->mutable_map_bool_bool())[1] = false;
-  (*message->mutable_map_string_string())["1"] = "2";
-  (*message->mutable_map_int32_bytes())[1] = "2";
-  (*message->mutable_map_int32_enum())[1] =
-      unittest::MAP_ENUM_FOO;
-  (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+  MapTestUtilImpl::ModifyMapFields<unittest::MapEnum, unittest::MAP_ENUM_FOO>(
+      message);
 }
 
 void MapTestUtil::ExpectClear(const unittest::TestMap& message) {
-  EXPECT_EQ(0, message.map_int32_int32().size());
-  EXPECT_EQ(0, message.map_int64_int64().size());
-  EXPECT_EQ(0, message.map_uint32_uint32().size());
-  EXPECT_EQ(0, message.map_uint64_uint64().size());
-  EXPECT_EQ(0, message.map_sint32_sint32().size());
-  EXPECT_EQ(0, message.map_sint64_sint64().size());
-  EXPECT_EQ(0, message.map_fixed32_fixed32().size());
-  EXPECT_EQ(0, message.map_fixed64_fixed64().size());
-  EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
-  EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
-  EXPECT_EQ(0, message.map_int32_float().size());
-  EXPECT_EQ(0, message.map_int32_double().size());
-  EXPECT_EQ(0, message.map_bool_bool().size());
-  EXPECT_EQ(0, message.map_string_string().size());
-  EXPECT_EQ(0, message.map_int32_bytes().size());
-  EXPECT_EQ(0, message.map_int32_enum().size());
-  EXPECT_EQ(0, message.map_int32_foreign_message().size());
+  MapTestUtilImpl::ExpectClear(message);
 }
 
 void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) {
-  EXPECT_EQ(2, message.map_int32_int32().size());
-  EXPECT_EQ(2, message.map_int64_int64().size());
-  EXPECT_EQ(2, message.map_uint32_uint32().size());
-  EXPECT_EQ(2, message.map_uint64_uint64().size());
-  EXPECT_EQ(2, message.map_sint32_sint32().size());
-  EXPECT_EQ(2, message.map_sint64_sint64().size());
-  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
-  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
-  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
-  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
-  EXPECT_EQ(2, message.map_int32_float().size());
-  EXPECT_EQ(2, message.map_int32_double().size());
-  EXPECT_EQ(2, message.map_bool_bool().size());
-  EXPECT_EQ(2, message.map_string_string().size());
-  EXPECT_EQ(2, message.map_int32_bytes().size());
-  EXPECT_EQ(2, message.map_int32_enum().size());
-  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+  MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+                                      unittest::MAP_ENUM_BAZ>(message);
+}
 
-  EXPECT_EQ(0, message.map_int32_int32().at(0));
-  EXPECT_EQ(0, message.map_int64_int64().at(0));
-  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
-  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
-  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
-  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
-  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
-  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
-  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
-  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
-  EXPECT_EQ(0, message.map_int32_float().at(0));
-  EXPECT_EQ(0, message.map_int32_double().at(0));
-  EXPECT_EQ(false, message.map_bool_bool().at(0));
-  EXPECT_EQ("0", message.map_string_string().at("0"));
-  EXPECT_EQ("0", message.map_int32_bytes().at(0));
-  EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
-  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-
-  EXPECT_EQ(1, message.map_int32_int32().at(1));
-  EXPECT_EQ(1, message.map_int64_int64().at(1));
-  EXPECT_EQ(1, message.map_uint32_uint32().at(1));
-  EXPECT_EQ(1, message.map_uint64_uint64().at(1));
-  EXPECT_EQ(1, message.map_sint32_sint32().at(1));
-  EXPECT_EQ(1, message.map_sint64_sint64().at(1));
-  EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
-  EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
-  EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
-  EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
-  EXPECT_EQ(1, message.map_int32_float().at(1));
-  EXPECT_EQ(1, message.map_int32_double().at(1));
-  EXPECT_EQ(true, message.map_bool_bool().at(1));
-  EXPECT_EQ("1", message.map_string_string().at("1"));
-  EXPECT_EQ("1", message.map_int32_bytes().at(1));
-  EXPECT_EQ(unittest::MAP_ENUM_BAZ, message.map_int32_enum().at(1));
-  EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+void MapTestUtil::ExpectArenaMapFieldsSet(
+    const unittest::TestArenaMap& message) {
+  MapTestUtilImpl::ExpectArenaMapFieldsSet<
+      unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>(
+      message);
 }
 
 void MapTestUtil::ExpectMapFieldsSetInitialized(
     const unittest::TestMap& message) {
-  EXPECT_EQ(1, message.map_int32_int32().size());
-  EXPECT_EQ(1, message.map_int64_int64().size());
-  EXPECT_EQ(1, message.map_uint32_uint32().size());
-  EXPECT_EQ(1, message.map_uint64_uint64().size());
-  EXPECT_EQ(1, message.map_sint32_sint32().size());
-  EXPECT_EQ(1, message.map_sint64_sint64().size());
-  EXPECT_EQ(1, message.map_fixed32_fixed32().size());
-  EXPECT_EQ(1, message.map_fixed64_fixed64().size());
-  EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
-  EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
-  EXPECT_EQ(1, message.map_int32_float().size());
-  EXPECT_EQ(1, message.map_int32_double().size());
-  EXPECT_EQ(1, message.map_bool_bool().size());
-  EXPECT_EQ(1, message.map_string_string().size());
-  EXPECT_EQ(1, message.map_int32_bytes().size());
-  EXPECT_EQ(1, message.map_int32_enum().size());
-  EXPECT_EQ(1, message.map_int32_foreign_message().size());
-
-  EXPECT_EQ(0, message.map_int32_int32().at(0));
-  EXPECT_EQ(0, message.map_int64_int64().at(0));
-  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
-  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
-  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
-  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
-  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
-  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
-  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
-  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
-  EXPECT_EQ(0, message.map_int32_float().at(0));
-  EXPECT_EQ(0, message.map_int32_double().at(0));
-  EXPECT_EQ(false, message.map_bool_bool().at(0));
-  EXPECT_EQ("", message.map_string_string().at("0"));
-  EXPECT_EQ("", message.map_int32_bytes().at(0));
-  EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(0));
-  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+  MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnum,
+                                                 unittest::MAP_ENUM_FOO>(
+      message);
 }
 
 void MapTestUtil::ExpectMapFieldsModified(
     const unittest::TestMap& message) {
-  // ModifyMapFields only sets the second element of each field.  In addition to
-  // verifying this, we also verify that the first element and size were *not*
-  // modified.
-  EXPECT_EQ(2, message.map_int32_int32().size());
-  EXPECT_EQ(2, message.map_int64_int64().size());
-  EXPECT_EQ(2, message.map_uint32_uint32().size());
-  EXPECT_EQ(2, message.map_uint64_uint64().size());
-  EXPECT_EQ(2, message.map_sint32_sint32().size());
-  EXPECT_EQ(2, message.map_sint64_sint64().size());
-  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
-  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
-  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
-  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
-  EXPECT_EQ(2, message.map_int32_float().size());
-  EXPECT_EQ(2, message.map_int32_double().size());
-  EXPECT_EQ(2, message.map_bool_bool().size());
-  EXPECT_EQ(2, message.map_string_string().size());
-  EXPECT_EQ(2, message.map_int32_bytes().size());
-  EXPECT_EQ(2, message.map_int32_enum().size());
-  EXPECT_EQ(2, message.map_int32_foreign_message().size());
-
-  EXPECT_EQ(0, message.map_int32_int32().at(0));
-  EXPECT_EQ(0, message.map_int64_int64().at(0));
-  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
-  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
-  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
-  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
-  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
-  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
-  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
-  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
-  EXPECT_EQ(0, message.map_int32_float().at(0));
-  EXPECT_EQ(0, message.map_int32_double().at(0));
-  EXPECT_EQ(false, message.map_bool_bool().at(0));
-  EXPECT_EQ("0", message.map_string_string().at("0"));
-  EXPECT_EQ("0", message.map_int32_bytes().at(0));
-  EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
-  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-
-  // Actually verify the second (modified) elements now.
-  EXPECT_EQ(2, message.map_int32_int32().at(1));
-  EXPECT_EQ(2, message.map_int64_int64().at(1));
-  EXPECT_EQ(2, message.map_uint32_uint32().at(1));
-  EXPECT_EQ(2, message.map_uint64_uint64().at(1));
-  EXPECT_EQ(2, message.map_sint32_sint32().at(1));
-  EXPECT_EQ(2, message.map_sint64_sint64().at(1));
-  EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
-  EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
-  EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
-  EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
-  EXPECT_EQ(2, message.map_int32_float().at(1));
-  EXPECT_EQ(2, message.map_int32_double().at(1));
-  EXPECT_EQ(false, message.map_bool_bool().at(1));
-  EXPECT_EQ("2", message.map_string_string().at("1"));
-  EXPECT_EQ("2", message.map_int32_bytes().at(1));
-  EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(1));
-  EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+  MapTestUtilImpl::ExpectMapFieldsModified<
+      unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>(
+      message);
 }
 
 void MapTestUtil::ExpectMapsSize(
@@ -1468,8 +1253,9 @@
     sub_message = reflection->AddMessage(message, F("map_int32_enum"));
     EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
                                                         key_descriptor));
-    EXPECT_EQ(0, sub_message->GetReflection()->GetEnum(*sub_message,
-                                                        value_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()
+                     ->GetEnum(*sub_message, value_descriptor)
+                     ->number());
   }
   // Map using message as value has been tested in other place. Thus, we don't
   // test it here.
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index 653cf10..f437e33 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -40,9 +40,12 @@
 
 class MapTestUtil {
  public:
-  // Set every field in the message to a unique value.
+  // Set every field in the TestMap message to a unique value.
   static void SetMapFields(unittest::TestMap* message);
 
+  // Set every field in the TestArenaMap message to a unique value.
+  static void SetArenaMapFields(unittest::TestArenaMap* message);
+
   // Set every field in the message to a default value.
   static void SetMapFieldsInitialized(unittest::TestMap* message);
 
@@ -55,6 +58,10 @@
   static void ExpectMapFieldsSet(const unittest::TestMap& message);
 
   // Check that all fields have the values that they should have after
+  // SetMapFields() is called for TestArenaMap.
+  static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message);
+
+  // Check that all fields have the values that they should have after
   // SetMapFieldsInitialized() is called.
   static void ExpectMapFieldsSetInitialized(
       const unittest::TestMap& message);
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
new file mode 100644
index 0000000..5e7882a
--- /dev/null
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -0,0 +1,474 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf_unittest {}  // forward declaration
+
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+
+class MapTestUtilImpl {
+ public:
+  // Set every field in the TestMap message to a unique value.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void SetMapFields(MapMessage* message);
+
+  // Set every field in the TestArenaMap message to a unique value.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void SetArenaMapFields(MapMessage* message);
+
+  // Set every field in the message to a default value.
+  template <typename MapMessage>
+  static void SetMapFieldsInitialized(MapMessage* message);
+
+  // Modify all the map fields of the messsage (which should already have been
+  // initialized with SetMapFields()).
+  template <typename EnumType, EnumType enum_value, typename MapMessage>
+  static void ModifyMapFields(MapMessage* message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void ExpectMapFieldsSet(const MapMessage& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called for TestArenaMap.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void ExpectArenaMapFieldsSet(const MapMessage& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFieldsInitialized() is called.
+  template <typename EnumType, EnumType enum_value, typename MapMessage>
+  static void ExpectMapFieldsSetInitialized(const MapMessage& message);
+
+  // Expect that the message is modified as would be expected from
+  // ModifyMapFields().
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void ExpectMapFieldsModified(const MapMessage& message);
+
+  // Check that all fields are empty.
+  template <typename MapMessage>
+  static void ExpectClear(const MapMessage& message);
+
+  // // Check that all map fields have the given size.
+  // template <typename MapMessage>
+  // static void ExpectMapsSize(const MapMessage& message, int size);
+
+  // // Get pointers of map entries at given index.
+  // static std::vector<const Message*> GetMapEntries(
+  //     const MapMessage& message, int index);
+
+  // // Get pointers of map entries from release.
+  // static std::vector<const Message*> GetMapEntriesFromRelease(
+  //     MapMessage* message);
+};
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetMapFields(MapMessage* message) {
+  // Add first element.
+  (*message->mutable_map_int32_int32())[0] = 0;
+  (*message->mutable_map_int64_int64())[0] = 0;
+  (*message->mutable_map_uint32_uint32())[0] = 0;
+  (*message->mutable_map_uint64_uint64())[0] = 0;
+  (*message->mutable_map_sint32_sint32())[0] = 0;
+  (*message->mutable_map_sint64_sint64())[0] = 0;
+  (*message->mutable_map_fixed32_fixed32())[0] = 0;
+  (*message->mutable_map_fixed64_fixed64())[0] = 0;
+  (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+  (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+  (*message->mutable_map_int32_float())[0] = 0.0;
+  (*message->mutable_map_int32_double())[0] = 0.0;
+  (*message->mutable_map_bool_bool())[0] = false;
+  (*message->mutable_map_string_string())["0"] = "0";
+  (*message->mutable_map_int32_bytes())[0] = "0";
+  (*message->mutable_map_int32_enum())[0] = enum_value0;
+  (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+  // Add second element
+  (*message->mutable_map_int32_int32())[1] = 1;
+  (*message->mutable_map_int64_int64())[1] = 1;
+  (*message->mutable_map_uint32_uint32())[1] = 1;
+  (*message->mutable_map_uint64_uint64())[1] = 1;
+  (*message->mutable_map_sint32_sint32())[1] = 1;
+  (*message->mutable_map_sint64_sint64())[1] = 1;
+  (*message->mutable_map_fixed32_fixed32())[1] = 1;
+  (*message->mutable_map_fixed64_fixed64())[1] = 1;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+  (*message->mutable_map_int32_float())[1] = 1.0;
+  (*message->mutable_map_int32_double())[1] = 1.0;
+  (*message->mutable_map_bool_bool())[1] = true;
+  (*message->mutable_map_string_string())["1"] = "1";
+  (*message->mutable_map_int32_bytes())[1] = "1";
+  (*message->mutable_map_int32_enum())[1] = enum_value1;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
+  // Add first element.
+  (*message->mutable_map_int32_int32())[0] = 0;
+  (*message->mutable_map_int64_int64())[0] = 0;
+  (*message->mutable_map_uint32_uint32())[0] = 0;
+  (*message->mutable_map_uint64_uint64())[0] = 0;
+  (*message->mutable_map_sint32_sint32())[0] = 0;
+  (*message->mutable_map_sint64_sint64())[0] = 0;
+  (*message->mutable_map_fixed32_fixed32())[0] = 0;
+  (*message->mutable_map_fixed64_fixed64())[0] = 0;
+  (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+  (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+  (*message->mutable_map_int32_float())[0] = 0.0;
+  (*message->mutable_map_int32_double())[0] = 0.0;
+  (*message->mutable_map_bool_bool())[0] = false;
+  (*message->mutable_map_int32_enum())[0] = enum_value0;
+  (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+  // Add second element
+  (*message->mutable_map_int32_int32())[1] = 1;
+  (*message->mutable_map_int64_int64())[1] = 1;
+  (*message->mutable_map_uint32_uint32())[1] = 1;
+  (*message->mutable_map_uint64_uint64())[1] = 1;
+  (*message->mutable_map_sint32_sint32())[1] = 1;
+  (*message->mutable_map_sint64_sint64())[1] = 1;
+  (*message->mutable_map_fixed32_fixed32())[1] = 1;
+  (*message->mutable_map_fixed64_fixed64())[1] = 1;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+  (*message->mutable_map_int32_float())[1] = 1.0;
+  (*message->mutable_map_int32_double())[1] = 1.0;
+  (*message->mutable_map_bool_bool())[1] = true;
+  (*message->mutable_map_int32_enum())[1] = enum_value1;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::SetMapFieldsInitialized(MapMessage* message) {
+  // Add first element using bracket operator, which should assign default
+  // value automatically.
+  (*message->mutable_map_int32_int32())[0];
+  (*message->mutable_map_int64_int64())[0];
+  (*message->mutable_map_uint32_uint32())[0];
+  (*message->mutable_map_uint64_uint64())[0];
+  (*message->mutable_map_sint32_sint32())[0];
+  (*message->mutable_map_sint64_sint64())[0];
+  (*message->mutable_map_fixed32_fixed32())[0];
+  (*message->mutable_map_fixed64_fixed64())[0];
+  (*message->mutable_map_sfixed32_sfixed32())[0];
+  (*message->mutable_map_sfixed64_sfixed64())[0];
+  (*message->mutable_map_int32_float())[0];
+  (*message->mutable_map_int32_double())[0];
+  (*message->mutable_map_bool_bool())[0];
+  (*message->mutable_map_string_string())["0"];
+  (*message->mutable_map_int32_bytes())[0];
+  (*message->mutable_map_int32_enum())[0];
+  (*message->mutable_map_int32_foreign_message())[0];
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ModifyMapFields(MapMessage* message) {
+  (*message->mutable_map_int32_int32())[1] = 2;
+  (*message->mutable_map_int64_int64())[1] = 2;
+  (*message->mutable_map_uint32_uint32())[1] = 2;
+  (*message->mutable_map_uint64_uint64())[1] = 2;
+  (*message->mutable_map_sint32_sint32())[1] = 2;
+  (*message->mutable_map_sint64_sint64())[1] = 2;
+  (*message->mutable_map_fixed32_fixed32())[1] = 2;
+  (*message->mutable_map_fixed64_fixed64())[1] = 2;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
+  (*message->mutable_map_int32_float())[1] = 2.0;
+  (*message->mutable_map_int32_double())[1] = 2.0;
+  (*message->mutable_map_bool_bool())[1] = false;
+  (*message->mutable_map_string_string())["1"] = "2";
+  (*message->mutable_map_int32_bytes())[1] = "2";
+  (*message->mutable_map_int32_enum())[1] = enum_value;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::ExpectClear(const MapMessage& message) {
+  EXPECT_EQ(0, message.map_int32_int32().size());
+  EXPECT_EQ(0, message.map_int64_int64().size());
+  EXPECT_EQ(0, message.map_uint32_uint32().size());
+  EXPECT_EQ(0, message.map_uint64_uint64().size());
+  EXPECT_EQ(0, message.map_sint32_sint32().size());
+  EXPECT_EQ(0, message.map_sint64_sint64().size());
+  EXPECT_EQ(0, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(0, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(0, message.map_int32_float().size());
+  EXPECT_EQ(0, message.map_int32_double().size());
+  EXPECT_EQ(0, message.map_bool_bool().size());
+  EXPECT_EQ(0, message.map_string_string().size());
+  EXPECT_EQ(0, message.map_int32_bytes().size());
+  EXPECT_EQ(0, message.map_int32_enum().size());
+  EXPECT_EQ(0, message.map_int32_foreign_message().size());
+}
+
+
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) {
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+  EXPECT_EQ(1, message.map_int64_int64().at(1));
+  EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(1, message.map_int32_float().at(1));
+  EXPECT_EQ(1, message.map_int32_double().at(1));
+  EXPECT_EQ(true, message.map_bool_bool().at(1));
+  EXPECT_EQ("1", message.map_string_string().at("1"));
+  EXPECT_EQ("1", message.map_int32_bytes().at(1));
+  EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+  EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+  EXPECT_EQ(1, message.map_int64_int64().at(1));
+  EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(1, message.map_int32_float().at(1));
+  EXPECT_EQ(1, message.map_int32_double().at(1));
+  EXPECT_EQ(true, message.map_bool_bool().at(1));
+  EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+  EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSetInitialized(
+    const MapMessage& message) {
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int64_int64().size());
+  EXPECT_EQ(1, message.map_uint32_uint32().size());
+  EXPECT_EQ(1, message.map_uint64_uint64().size());
+  EXPECT_EQ(1, message.map_sint32_sint32().size());
+  EXPECT_EQ(1, message.map_sint64_sint64().size());
+  EXPECT_EQ(1, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(1, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(1, message.map_int32_float().size());
+  EXPECT_EQ(1, message.map_int32_double().size());
+  EXPECT_EQ(1, message.map_bool_bool().size());
+  EXPECT_EQ(1, message.map_string_string().size());
+  EXPECT_EQ(1, message.map_int32_bytes().size());
+  EXPECT_EQ(1, message.map_int32_enum().size());
+  EXPECT_EQ(1, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("", message.map_string_string().at("0"));
+  EXPECT_EQ("", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+}
+
+template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsModified(
+    const MapMessage& message) {
+  // ModifyMapFields only sets the second element of each field.  In addition to
+  // verifying this, we also verify that the first element and size were *not*
+  // modified.
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(2, message.map_int32_int32().at(1));
+  EXPECT_EQ(2, message.map_int64_int64().at(1));
+  EXPECT_EQ(2, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(2, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(2, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(2, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(2, message.map_int32_float().at(1));
+  EXPECT_EQ(2, message.map_int32_double().at(1));
+  EXPECT_EQ(false, message.map_bool_bool().at(1));
+  EXPECT_EQ("2", message.map_string_string().at("1"));
+  EXPECT_EQ("2", message.map_int32_bytes().at(1));
+  EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+  EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+}
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 88a6d7b..278b78a 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__
 #define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
 
+#include <google/protobuf/arena.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 
 namespace google {
@@ -92,6 +92,28 @@
   static inline void Initialize(Type& value, int default_enum_value) {}
 };
 
+template <typename Type, bool is_arena_constructable>
+class MapArenaMessageCreator {
+ public:
+  // Use arena to create message if Type is arena constructable. Otherwise,
+  // create the message on heap.
+  static inline Type* CreateMessage(Arena* arena);
+};
+template <typename Type>
+class MapArenaMessageCreator<Type, true> {
+ public:
+  static inline Type* CreateMessage(Arena* arena) {
+    return Arena::CreateMessage<Type>(arena);
+  }
+};
+template <typename Type>
+class MapArenaMessageCreator<Type, false> {
+ public:
+  static inline Type* CreateMessage(Arena* arena) {
+    return new Type;
+  }
+};
+
 // Handlers for key/value stored type in MapField. ==================
 
 // Handler for message
@@ -124,20 +146,24 @@
     *value = const_cast<Type*>(&Type::default_instance());
   }
   // Initialize value when constructing MapEntry
-  static inline void Initialize(Type** x) { *x = NULL; }
+  static inline void Initialize(Type** x, Arena* arena) { *x = NULL; }
   // Same as above, but use default_enum_value to initialize enum type value.
   static inline void InitializeMaybeByDefaultEnum(
-      Type** x, int default_enum_value) {
+      Type** x, int default_enum_value, Arena* arena) {
     *x = NULL;
   }
   // Initialize value for the first time mutable accessor is called.
-  static inline void EnsureMutable(Type** value) {
-    if (*value == NULL) *value = new Type;
+  static inline void EnsureMutable(Type** value, Arena* arena) {
+    if (*value == NULL) {
+      *value =
+          MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
+                                           type::value>::CreateMessage(arena);
+    }
   }
   // Return default instance if value is not initialized when calling const
   // reference accessor.
-  static inline const Type& DefaultIfNotInitialized(Type* value,
-                                                    Type* default_value) {
+  static inline const Type& DefaultIfNotInitialized(const Type* value,
+                                                    const Type* default_value) {
     return value != NULL ? *value : *default_value;
   }
   // Check if all required fields have values set.
@@ -166,18 +192,23 @@
     if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
   }
   static inline void AssignDefaultValue(string** value) {}
-  static inline void Initialize(string** value) {
+  static inline void Initialize(string** value, Arena* arena) {
     *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+    if (arena != NULL) arena->Own(*value);
   }
   static inline void InitializeMaybeByDefaultEnum(
-      string** value, int default_enum_value) {
+      string** value, int default_enum_value, Arena* arena) {
     *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+    if (arena != NULL) arena->Own(*value);
   }
-  static inline void EnsureMutable(string** value) {
-    if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string;
+  static inline void EnsureMutable(string** value, Arena* arena) {
+    if (*value == &::google::protobuf::internal::GetEmptyString()) {
+      *value = Arena::Create<string>(arena);
+    }
   }
-  static inline const string& DefaultIfNotInitialized(string* value,
-                                                      string* default_value) {
+  static inline const string& DefaultIfNotInitialized(
+      const string* value,
+      const string* default_value) {
     return value != default_value ? *value : *default_value;
   }
   static inline bool IsInitialized(string* value) { return true; }
@@ -210,12 +241,13 @@
                                                int default_enum_value) {      \
       *value = static_cast<CType>(default_enum_value);                        \
     }                                                                         \
-    static inline void Initialize(CType* value) { *value = 0; }               \
+    static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \
     static inline void InitializeMaybeByDefaultEnum(CType* value,             \
-                                                    int default_enum_value) { \
+                                                    int default_enum_value,   \
+                                                    Arena* arena) {           \
       *value = static_cast<CType>(default_enum_value);                        \
     }                                                                         \
-    static inline void EnsureMutable(CType* value) {}                         \
+    static inline void EnsureMutable(CType* value, Arena* arena) {}           \
   };
 
 PRIMITIVE_HANDLER(int32 )
@@ -228,13 +260,13 @@
 
 #undef PRIMITIVE_HANDLER
 
-// Define constants for given proto field type
-template <FieldDescriptor::Type Type>
-class MapFieldTypeTraits {};
+// Define constants for given wire field type
+template <WireFormatLite::FieldType field_type>
+class MapWireFieldTypeTraits {};
 
 #define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
   template <>                                                            \
-  class MapFieldTypeTraits<FieldDescriptor::TYPE_##FieldType> {          \
+  class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType> {       \
    public:                                                               \
     typedef CType CppType;                                               \
     static const bool kIsMessage = IsMessage;                            \
@@ -243,7 +275,7 @@
         WireFormatLite::WIRETYPE_##WireFormatType;                       \
   };
 
-TYPE_TRAITS(MESSAGE , Message,  LENGTH_DELIMITED, true, false)
+TYPE_TRAITS(MESSAGE , MessageLite, LENGTH_DELIMITED, true, false)
 TYPE_TRAITS(STRING  , string ,  LENGTH_DELIMITED, false, false)
 TYPE_TRAITS(BYTES   , string ,  LENGTH_DELIMITED, false, false)
 TYPE_TRAITS(INT64   , int64  ,  VARINT , false, false)
@@ -263,51 +295,46 @@
 
 #undef TYPE_TRAITS
 
-// Handler for proto field type. Define types and constants used in compile
-// time. Also define functions used in parsing and serializing.
-template <FieldDescriptor::Type Type>
-class MapProtoTypeHandler {
+template <WireFormatLite::FieldType field_type>
+class MapWireFieldTypeHandler {
  public:
-  // Internal stored type in MapEntry for given proto field type.
-  typedef typename MapFieldTypeTraits<Type>::CppType CppType;
-
-  // Whether given type is a message.
-  static const bool kIsMessage = MapFieldTypeTraits<Type>::kIsMessage;
-
-  // Whether given type is an enum.
-  static const bool kIsEnum = MapFieldTypeTraits<Type>::kIsEnum;
-
-  // The wire type of given proto field type.
+  // Internal stored type in MapEntryLite for given wire field type.
+  typedef typename MapWireFieldTypeTraits<field_type>::CppType CppType;
+  // Corresponding wire type for field type.
   static const WireFormatLite::WireType kWireType =
-      MapFieldTypeTraits<Type>::kWireType;
+      MapWireFieldTypeTraits<field_type>::kWireType;
+  // Whether wire type is for message.
+  static const bool kIsMessage = MapWireFieldTypeTraits<field_type>::kIsMessage;
+  // Whether wire type is for enum.
+  static const bool kIsEnum = MapWireFieldTypeTraits<field_type>::kIsEnum;
 
   // Functions used in parsing and serialization. ===================
-
   template <typename ValueType>
   static inline int ByteSize(const ValueType& value);
   template <typename ValueType>
   static inline int GetCachedSize(const ValueType& value);
+  template <typename ValueType>
+  static inline bool Read(io::CodedInputStream* input, ValueType* value);
   static inline void Write(int field, const CppType& value,
                            io::CodedOutputStream* output);
   static inline uint8* WriteToArray(int field, const CppType& value,
                                     uint8* output);
-  template <typename ValueType>
-  static inline bool Read(io::CodedInputStream* input, ValueType* value);
 };
 
 template <>
 template <typename ValueType>
-inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::ByteSize(
+inline int MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::ByteSize(
     const ValueType& value) {
   return WireFormatLite::MessageSizeNoVirtual(value);
 }
 
-#define BYTE_SIZE(FieldType, DeclaredType)                                     \
-  template <>                                                                  \
-  template <typename ValueType>                                                \
-  inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
-      const ValueType& value) {                                                \
-    return WireFormatLite::DeclaredType##Size(value);                          \
+#define BYTE_SIZE(FieldType, DeclaredType)                             \
+  template <>                                                          \
+  template <typename ValueType>                                        \
+  inline int                                                           \
+  MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
+      const ValueType& value) {                                        \
+    return WireFormatLite::DeclaredType##Size(value);                  \
   }
 
 BYTE_SIZE(STRING, String)
@@ -322,12 +349,13 @@
 
 #undef BYTE_SIZE
 
-#define FIXED_BYTE_SIZE(FieldType, DeclaredType)                               \
-  template <>                                                                  \
-  template <typename ValueType>                                                \
-  inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
-      const ValueType& value) {                                                \
-    return WireFormatLite::k##DeclaredType##Size;                              \
+#define FIXED_BYTE_SIZE(FieldType, DeclaredType)                       \
+  template <>                                                          \
+  template <typename ValueType>                                        \
+  inline int                                                           \
+  MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
+      const ValueType& value) {                                        \
+    return WireFormatLite::k##DeclaredType##Size;                      \
   }
 
 FIXED_BYTE_SIZE(DOUBLE  , Double)
@@ -342,18 +370,18 @@
 
 template <>
 template <typename ValueType>
-inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::GetCachedSize(
-    const ValueType& value) {
+inline int MapWireFieldTypeHandler<
+    WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) {
   return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
 }
 
-#define GET_CACHED_SIZE(FieldType, DeclaredType)                         \
-  template <>                                                            \
-  template <typename ValueType>                                          \
-  inline int                                                             \
-  MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
-      const ValueType& value) {                                          \
-    return WireFormatLite::DeclaredType##Size(value);                    \
+#define GET_CACHED_SIZE(FieldType, DeclaredType)                            \
+  template <>                                                               \
+  template <typename ValueType>                                             \
+  inline int                                                                \
+  MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
+      const ValueType& value) {                                             \
+    return WireFormatLite::DeclaredType##Size(value);                       \
   }
 
 GET_CACHED_SIZE(STRING, String)
@@ -368,13 +396,13 @@
 
 #undef GET_CACHED_SIZE
 
-#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType)                   \
-  template <>                                                            \
-  template <typename ValueType>                                          \
-  inline int                                                             \
-  MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
-      const ValueType& value) {                                          \
-    return WireFormatLite::k##DeclaredType##Size;                        \
+#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType)                      \
+  template <>                                                               \
+  template <typename ValueType>                                             \
+  inline int                                                                \
+  MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
+      const ValueType& value) {                                             \
+    return WireFormatLite::k##DeclaredType##Size;                           \
   }
 
 GET_FIXED_CACHED_SIZE(DOUBLE  , Double)
@@ -388,26 +416,28 @@
 #undef GET_FIXED_CACHED_SIZE
 
 template <>
-inline void MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Write(
-    int field, const Message& value, io::CodedOutputStream* output) {
+inline void MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Write(
+    int field, const MessageLite& value, io::CodedOutputStream* output) {
   WireFormatLite::WriteMessageMaybeToArray(field, value, output);
 }
 
 template <>
-inline uint8* MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::WriteToArray(
-    int field, const Message& value, uint8* output) {
+inline uint8*
+MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::WriteToArray(
+    int field, const MessageLite& value, uint8* output) {
   return WireFormatLite::WriteMessageToArray(field, value, output);
 }
 
 #define WRITE_METHOD(FieldType, DeclaredType)                                  \
   template <>                                                                  \
-  inline void MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Write(   \
+  inline void                                                                  \
+  MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Write(            \
       int field, const CppType& value, io::CodedOutputStream* output) {        \
     return WireFormatLite::Write##DeclaredType(field, value, output);          \
   }                                                                            \
   template <>                                                                  \
   inline uint8*                                                                \
-  MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::WriteToArray(        \
+  MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::WriteToArray(     \
       int field, const CppType& value, uint8* output) {                        \
     return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
   }
@@ -433,33 +463,33 @@
 
 template <>
 template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Read(
     io::CodedInputStream* input, ValueType* value) {
   return WireFormatLite::ReadMessageNoVirtual(input, value);
 }
 
 template <>
 template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_STRING>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_STRING>::Read(
     io::CodedInputStream* input, ValueType* value) {
   return WireFormatLite::ReadString(input, value);
 }
 
 template <>
 template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_BYTES>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_BYTES>::Read(
     io::CodedInputStream* input, ValueType* value) {
   return WireFormatLite::ReadBytes(input, value);
 }
 
-#define READ_METHOD(FieldType)                                              \
-  template <>                                                               \
-  template <typename ValueType>                                             \
-  inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Read( \
-      io::CodedInputStream* input, ValueType* value) {                      \
-    return WireFormatLite::ReadPrimitive<CppType,                           \
-                                         WireFormatLite::TYPE_##FieldType>( \
-        input, value);                                                      \
+#define READ_METHOD(FieldType)                                                 \
+  template <>                                                                  \
+  template <typename ValueType>                                                \
+  inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Read( \
+      io::CodedInputStream* input, ValueType* value) {                         \
+    return WireFormatLite::ReadPrimitive<CppType,                              \
+                                         WireFormatLite::TYPE_##FieldType>(    \
+        input, value);                                                         \
   }
 
 READ_METHOD(INT64)
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index 9232d58..830f672 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -30,6 +30,7 @@
 
 syntax = "proto3";
 
+option cc_enable_arenas = true;
 
 import "google/protobuf/unittest.proto";
 
@@ -59,6 +60,10 @@
   map<int32   , ForeignMessage> map_int32_foreign_message = 17;
 }
 
+message TestMapSubmessage {
+  optional TestMap test_map = 1;
+}
+
 message TestMessageMap {
   map<int32, TestAllTypes> map_int32_message = 1;
 }
@@ -80,3 +85,21 @@
 message TestRequiredMessageMap {
   map<int32, TestRequired> map_field = 1;
 }
+
+message TestArenaMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<int32   , MapEnum > map_int32_enum        = 14;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 15;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index afe9546..f58be84 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -441,6 +441,30 @@
 }
 
 namespace internal {
+namespace {
+void ShutdownRepeatedFieldAccessor() {
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown();
+  internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown();
+  internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown();
+  internal::Singleton<internal::MapFieldAccessor>::ShutDown();
+}
+
+struct ShutdownRepeatedFieldRegister {
+  ShutdownRepeatedFieldRegister() {
+    OnShutdown(&ShutdownRepeatedFieldAccessor);
+  }
+} shutdown_;
+
+}  // namespace
+}  // namespace internal
+
+namespace internal {
 // Macro defined in repeated_field.h. We can only define the Message-specific
 // GenericTypeHandler specializations here because we depend on Message, which
 // is not part of proto2-lite hence is not available in repeated_field.h.
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index a200bc9..6e1929e 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -208,7 +208,7 @@
   // This is much, much slower than IsInitialized() as it is implemented
   // purely via reflection.  Generally, you should not call this unless you
   // have already determined that an error exists by calling IsInitialized().
-  void FindInitializationErrors(vector<string>* errors) const;
+  void FindInitializationErrors(std::vector<string>* errors) const;
 
   // Like FindInitializationErrors, but joins all the strings, delimited by
   // commas, and returns them.
@@ -456,7 +456,7 @@
   // Swap fields listed in fields vector of two messages.
   virtual void SwapFields(Message* message1,
                           Message* message2,
-                          const vector<const FieldDescriptor*>& fields)
+                          const std::vector<const FieldDescriptor*>& fields)
       const = 0;
 
   // Swap two elements of a repeated field.
@@ -470,8 +470,9 @@
   // return true and repeated fields will only be listed if FieldSize(field)
   // would return non-zero.  Fields (both normal fields and extension fields)
   // will be listed ordered by field number.
-  virtual void ListFields(const Message& message,
-                          vector<const FieldDescriptor*>* output) const = 0;
+  virtual void ListFields(
+      const Message& message,
+      std::vector<const FieldDescriptor*>* output) const = 0;
 
   // Singular field getters ------------------------------------------
   // These get the value of a non-repeated field.  They return the default
@@ -523,7 +524,7 @@
   //   regardless of the field's underlying representation.  When initializing
   //   a newly-constructed string, though, it's just as fast and more readable
   //   to use code like:
-  //     string str = reflection->GetString(field);
+  //     string str = reflection->GetString(message, field);
   virtual const string& GetStringReference(const Message& message,
                                            const FieldDescriptor* field,
                                            string* scratch) const = 0;
@@ -842,6 +843,19 @@
   // }
   virtual bool SupportsUnknownEnumValues() const { return false; }
 
+  // Returns the MessageFactory associated with this message.  This can be
+  // useful for determining if a message is a generated message or not, for
+  // example:
+  //
+  // if (message->GetReflection()->GetMessageFactory() ==
+  //     google::protobuf::MessageFactory::generated_factory()) {
+  //   // This is a generated message.
+  // }
+  //
+  // It can also be used to create more messages of this type, though
+  // Message::New() is an easier way to accomplish this.
+  virtual MessageFactory* GetMessageFactory() const;
+
   // ---------------------------------------------------------------------------
 
  protected:
@@ -854,8 +868,6 @@
       Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
       int ctype, const Descriptor* message_type) const = 0;
 
-  virtual MessageFactory* GetMessageFactory() const;
-
   // The following methods are used to implement (Mutable)RepeatedFieldRef.
   // A Ref object will store a raw pointer to the repeated field data (obtained
   // from RepeatedFieldData()) and a pointer to a Accessor (obtained from
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 106982c..eab61c1 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -41,6 +41,7 @@
 
 #include <google/protobuf/stubs/common.h>
 
+
 namespace google {
 namespace protobuf {
   class Arena;
@@ -133,9 +134,10 @@
   // just simple wrappers around MergeFromCodedStream().  Clear() will be called
   // before merging the input.
 
-  // Fill the message with a protocol buffer parsed from the given input
-  // stream.  Returns false on a read error or if the input is in the
-  // wrong format.
+  // Fill the message with a protocol buffer parsed from the given input stream.
+  // Returns false on a read error or if the input is in the wrong format.  A
+  // successful return does not indicate the entire input is consumed, ensure
+  // you call ConsumedEntireMessage() to check that if applicable.
   bool ParseFromCodedStream(io::CodedInputStream* input);
   // Like ParseFromCodedStream(), but accepts messages that are missing
   // required fields.
@@ -154,7 +156,11 @@
   // missing required fields.
   bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
                                              int size);
-  // Parse a protocol buffer contained in a string.
+  // Parses a protocol buffer contained in a string. Returns true on success.
+  // This function takes a string in the (non-human-readable) binary wire
+  // format, matching the encoding output by MessageLite::SerializeToString().
+  // If you'd like to convert a human-readable string into a protocol buffer
+  // object, see google::protobuf::TextFormat::ParseFromString().
   bool ParseFromString(const string& data);
   // Like ParseFromString(), but accepts messages that are missing
   // required fields.
diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc
deleted file mode 100644
index baf42ff..0000000
--- a/src/google/protobuf/new_delete_capture.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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 exists for testing allocation behavior when using arenas by hooking
-// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc.
-
-#include <google/protobuf/new_delete_capture.h>
-
-#include <pthread.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/malloc_hook.h>
-#include <google/protobuf/stubs/spinlock.h>
-
-namespace google {
-namespace {
-
-pthread_t gthread;
-protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL;
-SpinLock gspinlock(base::LINKER_INITIALIZED);
-
-}  // namespace
-
-namespace protobuf_unittest {
-
-NewDeleteCapture::NewDeleteCapture()
-    : alloc_count_(0),
-      alloc_size_(0),
-      alloc_ptr_(NULL),
-      free_count_(0),
-      free_ptr_(NULL) {}
-
-NewDeleteCapture::~NewDeleteCapture() { Unhook(); }
-
-void NewDeleteCapture::Reset() {
-  alloc_count_ = 0;
-  alloc_size_ = 0;
-  free_count_ = 0;
-  alloc_ptr_ = NULL;
-  free_ptr_ = NULL;
-}
-
-bool NewDeleteCapture::Hook(bool reset) {
-  SpinLockHolder spinlock(&gspinlock);
-  if (ghooked_instance != this) {
-    GOOGLE_CHECK(ghooked_instance == NULL)
-        << " NewDeleteCapture can have only 1 active instance";
-    GOOGLE_CHECK(MallocHook::AddNewHook(NewHook));
-    GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook));
-    gthread = pthread_self();
-    ghooked_instance = this;
-    if (reset) {
-      Reset();
-    }
-    return true;
-  }
-  return false;
-}
-
-bool NewDeleteCapture::Unhook() {
-  SpinLockHolder spinlock(&gspinlock);
-  if (ghooked_instance == this) {
-    gthread = pthread_t();
-    ghooked_instance = NULL;
-    GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook));
-    GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook));
-    return true;
-  }
-  return false;
-}
-
-void NewDeleteCapture::NewHook(const void *ptr, size_t size) {
-  SpinLockHolder spinlock(&gspinlock);
-  if (gthread == pthread_self()) {
-    auto &rthis = *ghooked_instance;
-    if (++rthis.alloc_count_ == 1) {
-      rthis.alloc_size_ = size;
-      rthis.alloc_ptr_ = ptr;
-    }
-  }
-}
-
-void NewDeleteCapture::DeleteHook(const void *ptr) {
-  SpinLockHolder spinlock(&gspinlock);
-  if (gthread == pthread_self()) {
-    auto &rthis = *ghooked_instance;
-    if (++rthis.free_count_ == 1) {
-      rthis.free_ptr_ = ptr;
-    }
-  }
-}
-
-}  // namespace protobuf_unittest
-}  // namespace google
diff --git a/src/google/protobuf/new_delete_capture.h b/src/google/protobuf/new_delete_capture.h
deleted file mode 100644
index 4ab550c..0000000
--- a/src/google/protobuf/new_delete_capture.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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 exists for testing allocation behavior when using arenas by hooking
-// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.h.
-//
-// Copyright 2014 Google Inc.
-//
-// Author: Martijn Vels
-//
-// A simple class that captures memory allocations and deletes.
-//
-// This class is private to //strings and only intended to be used inside
-// unit tests. It uses the MallocHook functionality to capture memory
-// allocation and delete operations performed by the thread that activated
-// a hook on a specific instance.
-//
-// The class  captures the following information:
-// - Total allocation count (new, malloc(), etc).
-// - Total delete count (delete, free(), etc).
-// - The size and returned pointer for the first memory allocation.
-// - The pointer for the first delete operation.
-//
-// The latter 2 infos (size and pointer of first new/delete) are usefull in
-// cases where you can closely scope a Hook() / Unhook sequence around a
-// specific piece of code where you expect no more than 1 pair of new / delete
-// operations.
-//
-// Sample usage where we expect a single unique alloc / free:
-//
-//   NewDeleteCapture capture_alloc;
-//   const void *ptr;
-//   {
-//     capture_alloc.Hook();
-//     MyAllocationClass my_instance(size);
-//     capture_alloc.Unhook();
-//
-//     ptr = my_instance.ptr();
-//     GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
-//     GOOGLE_CHECK_EQ(0, capture_alloc.free_count());
-//     GOOGLE_CHECK_EQ(size, capture_alloc.alloc_size());
-//     GOOGLE_CHECK_EQ(ptr, capture_alloc.alloc_ptr());
-//
-//     capture_alloc.Hook();
-//   }
-//   capture_alloc.Unhook();
-//   GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
-//   GOOGLE_CHECK_EQ(1, capture_alloc.free_count());
-//   GOOGLE_CHECK_EQ(ptr, capture_alloc.free_ptr());
-//
-// You can only have one NewDeleteCapture instance active at the time. It is
-// total valid to have many instances in different threads, but only one
-// instance can have a hook active.
-//
-// Legal:
-//
-//   NewDeleteCapture capture_alloc1;
-//   NewDeleteCapture capture_alloc2;
-//   const void *ptr;
-//   {
-//     capture_alloc1.Hook();
-//     MyAllocationClass my_instance(size);
-//     capture_alloc1.Unhook();
-//
-//     capture_alloc2.Hook();
-//     my_instance.reset(size);
-//     capture_alloc2.Unhook();
-//   }
-//
-// Illegal:
-//
-//   NewDeleteCapture capture_alloc1;
-//   NewDeleteCapture capture_alloc2;
-//   const void *ptr;
-//   {
-//     capture_alloc1.Hook();
-//     MyAllocationClass my_instance(size);
-//
-//     capture_alloc2.Hook();
-//     my_instance.reset(size);
-//
-//     capture_alloc1.Unhook();
-//     capture_alloc2.Unhook();
-//   }
-//
-#ifndef GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
-#define GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
-
-#include <stddef.h>
-
-namespace google {
-namespace protobuf_unittest {
-
-class NewDeleteCapture {
- public:
-  // Creates a new inactive capture instance
-  NewDeleteCapture();
-
-  // Destroys this capture instance. Active hooks are automatically removed.
-  ~NewDeleteCapture();
-
-  // Activates a hook on this instance. If reset is true (the default), all
-  // internal counters will be reset to 0.
-  // Returns true if the hook was activated, false if this instance already
-  // owned the hook.
-  // Requires no other instance owning the hook (check fails)
-  bool Hook(bool reset = true);
-
-  // De-activate the hook on this instance.
-  // Returns true if the hook was removed, false if this instance did not own
-  // the hook.
-  bool Unhook();
-
-  // Resets all counters to 0
-  void Reset();
-
-  // Returns the total number of allocations (new, malloc(), etc)
-  size_t alloc_count() const { return alloc_count_; }
-
-  // Returns the total number of deletes (delete, free(), etc)
-  size_t free_count() const { return free_count_; }
-
-  // Returns the size of the first observed allocation
-  size_t alloc_size() const { return alloc_size_; }
-
-  // Returns the allocated ptr of the first observed allocation
-  const void *alloc_ptr() const { return alloc_ptr_; }
-
-  // Returns the ptr of the first observed delete
-  const void* free_ptr() const { return free_ptr_; }
-
- private:
-  static void NewHook(const void *ptr, size_t size);
-  static void DeleteHook(const void *ptr);
-
- private:
-  size_t alloc_count_;
-  size_t alloc_size_;
-  const void *alloc_ptr_;
-
-  size_t free_count_;
-  const void *free_ptr_;
-};
-
-}  // namespace protobuf_unittest
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 816e52c..9f8703a 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_preserve_unknown_enum.pb.h>
+#include <google/protobuf/unittest_preserve_unknown_enum2.pb.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/descriptor.h>
 #include <gtest/gtest.h>
@@ -39,46 +40,55 @@
 namespace {
 
 void FillMessage(
-    proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
+    proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
   message->set_e(
-      proto2_preserve_unknown_enum_unittest::E_EXTRA);
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
   message->add_repeated_e(
-      proto2_preserve_unknown_enum_unittest::E_EXTRA);
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
   message->add_repeated_packed_e(
-      proto2_preserve_unknown_enum_unittest::E_EXTRA);
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
+  message->add_repeated_packed_unexpected_e(
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
   message->set_oneof_e_1(
-      proto2_preserve_unknown_enum_unittest::E_EXTRA);
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
 }
 
 void CheckMessage(
-    const proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
-  EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+    const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
             message.e());
   EXPECT_EQ(1, message.repeated_e_size());
-  EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
             message.repeated_e(0));
   EXPECT_EQ(1, message.repeated_packed_e_size());
-  EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
             message.repeated_packed_e(0));
-  EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+  EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+            message.repeated_packed_unexpected_e(0));
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
             message.oneof_e_1());
 }
 
 void CheckMessage(
-    const proto2_preserve_unknown_enum_unittest::MyMessage& message) {
+    const proto3_preserve_unknown_enum_unittest::MyMessage& message) {
   EXPECT_EQ(static_cast<int>(
-              proto2_preserve_unknown_enum_unittest::E_EXTRA),
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
             static_cast<int>(message.e()));
   EXPECT_EQ(1, message.repeated_e_size());
   EXPECT_EQ(static_cast<int>(
-              proto2_preserve_unknown_enum_unittest::E_EXTRA),
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
             static_cast<int>(message.repeated_e(0)));
   EXPECT_EQ(1, message.repeated_packed_e_size());
   EXPECT_EQ(static_cast<int>(
-              proto2_preserve_unknown_enum_unittest::E_EXTRA),
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
             static_cast<int>(message.repeated_packed_e(0)));
+  EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
   EXPECT_EQ(static_cast<int>(
-              proto2_preserve_unknown_enum_unittest::E_EXTRA),
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
+            static_cast<int>(message.repeated_packed_unexpected_e(0)));
+  EXPECT_EQ(static_cast<int>(
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
             static_cast<int>(message.oneof_e_1()));
 }
 
@@ -87,12 +97,12 @@
 // Test that parsing preserves an unknown value in the enum field and does not
 // punt it to the UnknownFieldSet.
 TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
-  proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
   FillMessage(&orig_message);
   string serialized;
   orig_message.SerializeToString(&serialized);
 
-  proto2_preserve_unknown_enum_unittest::MyMessage message;
+  proto3_preserve_unknown_enum_unittest::MyMessage message;
   EXPECT_EQ(true, message.ParseFromString(serialized));
   CheckMessage(message);
 
@@ -105,13 +115,13 @@
 // Test that reflection based implementation also keeps unknown enum values and
 // doesn't put them into UnknownFieldSet.
 TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
-  proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
   FillMessage(&orig_message);
   string serialized = orig_message.SerializeAsString();
 
   google::protobuf::DynamicMessageFactory factory;
   google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
-      proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+      proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
   EXPECT_EQ(true, message->ParseFromString(serialized));
   message->DiscardUnknownFields();
 
@@ -120,15 +130,62 @@
   CheckMessage(orig_message);
 }
 
-// Test that reflection provides EnumValueDescriptors for unknown values.
-TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
-  proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+// Test that for proto2 messages, unknown values are in unknown fields.
+TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
   FillMessage(&orig_message);
+
   string serialized;
   orig_message.SerializeToString(&serialized);
 
   proto2_preserve_unknown_enum_unittest::MyMessage message;
   EXPECT_EQ(true, message.ParseFromString(serialized));
+  // The intermediate message has everything in its "unknown fields".
+  proto2_preserve_unknown_enum_unittest::MyMessage message2 = message;
+  message2.DiscardUnknownFields();
+  EXPECT_EQ(0, message2.ByteSize());
+
+  // But when we pass it to the correct structure, all values are there.
+  serialized.clear();
+  message.SerializeToString(&serialized);
+  EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+  CheckMessage(orig_message);
+}
+
+// Same as before, for a dynamic message.
+TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+
+  string serialized;
+  orig_message.SerializeToString(&serialized);
+
+  google::protobuf::DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+      proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+  EXPECT_EQ(true, message->ParseFromString(serialized));
+  // The intermediate message has everything in its "unknown fields".
+  proto2_preserve_unknown_enum_unittest::MyMessage message2;
+  message2.CopyFrom(*message);
+  message2.DiscardUnknownFields();
+  EXPECT_EQ(0, message2.ByteSize());
+
+  // But when we pass it to the correct structure, all values are there.
+  serialized.clear();
+  message->SerializeToString(&serialized);
+  EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+  CheckMessage(orig_message);
+}
+
+// Test that reflection provides EnumValueDescriptors for unknown values.
+TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+  string serialized;
+  orig_message.SerializeToString(&serialized);
+
+  proto3_preserve_unknown_enum_unittest::MyMessage message;
+  EXPECT_EQ(true, message.ParseFromString(serialized));
   CheckMessage(message);
 
   const google::protobuf::Reflection* r = message.GetReflection();
@@ -138,7 +195,7 @@
   // This should dynamically create an EnumValueDescriptor.
   const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field);
   EXPECT_EQ(enum_value->number(),
-            static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+            static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
 
   // Fetching value for a second time should return the same pointer.
   const google::protobuf::EnumValueDescriptor* enum_value_second =
@@ -150,7 +207,7 @@
       d->FindFieldByName("repeated_e");
   enum_value = r->GetRepeatedEnum(message, repeated_field, 0);
   EXPECT_EQ(enum_value->number(),
-            static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+            static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
   // Should reuse the same EnumValueDescriptor, even for a different field.
   EXPECT_EQ(enum_value, enum_value_second);
 
@@ -164,7 +221,7 @@
 
 // Test that the new integer-based enum reflection API works.
 TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) {
-  proto2_preserve_unknown_enum_unittest::MyMessage message;
+  proto3_preserve_unknown_enum_unittest::MyMessage message;
   const google::protobuf::Reflection* r = message.GetReflection();
   const google::protobuf::Descriptor* d = message.GetDescriptor();
 
@@ -220,7 +277,7 @@
 
 TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) {
   protobuf_unittest::TestAllTypes proto2_message;
-  proto2_preserve_unknown_enum_unittest::MyMessage new_message;
+  proto3_preserve_unknown_enum_unittest::MyMessage new_message;
 
   const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection();
   const google::protobuf::Reflection* new_reflection = new_message.GetReflection();
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
old mode 100644
new mode 100755
index 17d89a1..03c761c
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -33,6 +33,11 @@
 #ifndef GOOGLE_PROTOBUF_REFLECTION_H__
 #define GOOGLE_PROTOBUF_REFLECTION_H__
 
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
 #include <google/protobuf/message.h>
 
 namespace google {
@@ -223,7 +228,7 @@
   const Message* default_instance_;
 };
 
-// MutableRepeatedFieldRef definition for non-message types.
+// MutableRepeatedFieldRef definition for message types.
 template<typename T>
 class MutableRepeatedFieldRef<
     T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
@@ -297,10 +302,298 @@
   const AccessorType* accessor_;
   const Message* default_instance_;
 };
+
+namespace internal {
+// Interfaces used to implement reflection RepeatedFieldRef API.
+// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
+// object that implements the below interface.
+//
+// This interface passes/returns values using void pointers. The actual type
+// of the value depends on the field's cpp_type. Following is a mapping from
+// cpp_type to the type that should be used in this interface:
+//
+//   field->cpp_type()      T                Actual type of void*
+//   CPPTYPE_INT32        int32                   int32
+//   CPPTYPE_UINT32       uint32                  uint32
+//   CPPTYPE_INT64        int64                   int64
+//   CPPTYPE_UINT64       uint64                  uint64
+//   CPPTYPE_DOUBLE       double                  double
+//   CPPTYPE_FLOAT        float                   float
+//   CPPTYPE_BOOL         bool                    bool
+//   CPPTYPE_ENUM         generated enum type     int32
+//   CPPTYPE_STRING       string                  string
+//   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
+//                        or google::protobuf::Message
+//
+// Note that for enums we use int32 in the interface.
+//
+// You can map from T to the actual type using RefTypeTraits:
+//   typedef RefTypeTraits<T>::AccessorValueType ActualType;
+class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
+ public:
+  // Typedefs for clarity.
+  typedef void Field;
+  typedef void Value;
+  typedef void Iterator;
+
+  virtual ~RepeatedFieldAccessor();
+  virtual bool IsEmpty(const Field* data) const = 0;
+  virtual int Size(const Field* data) const = 0;
+  // Depends on the underlying representation of the repeated field, this
+  // method can return a pointer to the underlying object if such an object
+  // exists, or fill the data into scratch_space and return scratch_space.
+  // Callers of this method must ensure scratch_space is a valid pointer
+  // to a mutable object of the correct type.
+  virtual const Value* Get(
+      const Field* data, int index, Value* scratch_space) const = 0;
+
+  virtual void Clear(Field* data) const = 0;
+  virtual void Set(Field* data, int index, const Value* value) const = 0;
+  virtual void Add(Field* data, const Value* value) const = 0;
+  virtual void RemoveLast(Field* data) const = 0;
+  virtual void SwapElements(Field* data, int index1, int index2) const = 0;
+  virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
+                    Field* other_data) const = 0;
+
+  // Create an iterator that points at the begining of the repeated field.
+  virtual Iterator* BeginIterator(const Field* data) const = 0;
+  // Create an iterator that points at the end of the repeated field.
+  virtual Iterator* EndIterator(const Field* data) const = 0;
+  // Make a copy of an iterator and return the new copy.
+  virtual Iterator* CopyIterator(const Field* data,
+                                 const Iterator* iterator) const = 0;
+  // Move an iterator to point to the next element.
+  virtual Iterator* AdvanceIterator(const Field* data,
+                                    Iterator* iterator) const = 0;
+  // Compare whether two iterators point to the same element.
+  virtual bool EqualsIterator(const Field* data, const Iterator* a,
+                              const Iterator* b) const = 0;
+  // Delete an iterator created by BeginIterator(), EndIterator() and
+  // CopyIterator().
+  virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
+  // Like Get() but for iterators.
+  virtual const Value* GetIteratorValue(const Field* data,
+                                        const Iterator* iterator,
+                                        Value* scratch_space) const = 0;
+
+  // Templated methods that make using this interface easier for non-message
+  // types.
+  template<typename T>
+  T Get(const Field* data, int index) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    ActualType scratch_space;
+    return static_cast<T>(
+        *reinterpret_cast<const ActualType*>(
+            Get(data, index, static_cast<Value*>(&scratch_space))));
+  }
+
+  template<typename T, typename ValueType>
+  void Set(Field* data, int index, const ValueType& value) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    // In this RepeatedFieldAccessor interface we pass/return data using
+    // raw pointers. Type of the data these raw pointers point to should
+    // be ActualType. Here we have a ValueType object and want a ActualType
+    // pointer. We can't cast a ValueType pointer to an ActualType pointer
+    // directly because their type might be different (for enums ValueType
+    // may be a generated enum type while ActualType is int32). To be safe
+    // we make a copy to get a temporary ActualType object and use it.
+    ActualType tmp = static_cast<ActualType>(value);
+    Set(data, index, static_cast<const Value*>(&tmp));
+  }
+
+  template<typename T, typename ValueType>
+  void Add(Field* data, const ValueType& value) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    // In this RepeatedFieldAccessor interface we pass/return data using
+    // raw pointers. Type of the data these raw pointers point to should
+    // be ActualType. Here we have a ValueType object and want a ActualType
+    // pointer. We can't cast a ValueType pointer to an ActualType pointer
+    // directly because their type might be different (for enums ValueType
+    // may be a generated enum type while ActualType is int32). To be safe
+    // we make a copy to get a temporary ActualType object and use it.
+    ActualType tmp = static_cast<ActualType>(value);
+    Add(data, static_cast<const Value*>(&tmp));
+  }
+};
+
+// Implement (Mutable)RepeatedFieldRef::iterator
+template<typename T>
+class RepeatedFieldRefIterator
+    : public std::iterator<std::forward_iterator_tag, T> {
+  typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
+  typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
+  typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
+
+ public:
+  // Constructor for non-message fields.
+  RepeatedFieldRefIterator(const void* data,
+                           const RepeatedFieldAccessor* accessor,
+                           bool begin)
+      : data_(data), accessor_(accessor),
+        iterator_(begin ? accessor->BeginIterator(data) :
+                          accessor->EndIterator(data)),
+        scratch_space_(new AccessorValueType) {
+  }
+  // Constructor for message fields.
+  RepeatedFieldRefIterator(const void* data,
+                           const RepeatedFieldAccessor* accessor,
+                           bool begin,
+                           AccessorValueType* scratch_space)
+      : data_(data), accessor_(accessor),
+        iterator_(begin ? accessor->BeginIterator(data) :
+                          accessor->EndIterator(data)),
+        scratch_space_(scratch_space) {
+  }
+  ~RepeatedFieldRefIterator() {
+    accessor_->DeleteIterator(data_, iterator_);
+  }
+  RepeatedFieldRefIterator operator++(int) {
+    RepeatedFieldRefIterator tmp(*this);
+    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+    return tmp;
+  }
+  RepeatedFieldRefIterator& operator++() {
+    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+    return *this;
+  }
+  IteratorValueType operator*() const {
+    return static_cast<IteratorValueType>(
+        *static_cast<const AccessorValueType*>(
+            accessor_->GetIteratorValue(
+                data_, iterator_, scratch_space_.get())));
+  }
+  IteratorPointerType operator->() const {
+    return static_cast<IteratorPointerType>(
+        accessor_->GetIteratorValue(
+            data_, iterator_, scratch_space_.get()));
+  }
+  bool operator!=(const RepeatedFieldRefIterator& other) const {
+    assert(data_ == other.data_);
+    assert(accessor_ == other.accessor_);
+    return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
+  }
+  bool operator==(const RepeatedFieldRefIterator& other) const {
+    return !this->operator!=(other);
+  }
+
+  RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
+      : data_(other.data_), accessor_(other.accessor_),
+        iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
+  }
+  RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
+    if (this != &other) {
+      accessor_->DeleteIterator(data_, iterator_);
+      data_ = other.data_;
+      accessor_ = other.accessor_;
+      iterator_ = accessor_->CopyIterator(data_, other.iterator_);
+    }
+    return *this;
+  }
+
+ protected:
+  const void* data_;
+  const RepeatedFieldAccessor* accessor_;
+  void* iterator_;
+  google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
+};
+
+// TypeTraits that maps the type parameter T of RepeatedFieldRef or
+// MutableRepeatedFieldRef to corresponding iterator type,
+// RepeatedFieldAccessor type, etc.
+template<typename T>
+struct PrimitiveTraits {
+  static const bool is_primitive = false;
+};
+#define DEFINE_PRIMITIVE(TYPE, type) \
+    template<> struct PrimitiveTraits<type> { \
+      static const bool is_primitive = true; \
+      static const FieldDescriptor::CppType cpp_type = \
+          FieldDescriptor::CPPTYPE_ ## TYPE; \
+    };
+DEFINE_PRIMITIVE(INT32, int32)
+DEFINE_PRIMITIVE(UINT32, uint32)
+DEFINE_PRIMITIVE(INT64, int64)
+DEFINE_PRIMITIVE(UINT64, uint64)
+DEFINE_PRIMITIVE(FLOAT, float)
+DEFINE_PRIMITIVE(DOUBLE, double)
+DEFINE_PRIMITIVE(BOOL, bool)
+#undef DEFINE_PRIMITIVE
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef T AccessorValueType;
+  typedef T IteratorValueType;
+  typedef T* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      PrimitiveTraits<T>::cpp_type;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  // We use int32 for repeated enums in RepeatedFieldAccessor.
+  typedef int32 AccessorValueType;
+  typedef T IteratorValueType;
+  typedef int32* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_ENUM;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef string AccessorValueType;
+  typedef string IteratorValueType;
+  typedef string* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_STRING;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct MessageDescriptorGetter {
+  static const Descriptor* get() {
+    return T::default_instance().GetDescriptor();
+  }
+};
+template<>
+struct MessageDescriptorGetter<Message> {
+  static const Descriptor* get() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef Message AccessorValueType;
+  typedef const T& IteratorValueType;
+  typedef const T* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_MESSAGE;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return MessageDescriptorGetter<T>::get();
+  }
+};
+}  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-// Implementation details for (Mutable)RepeatedFieldRef.
-#include <google/protobuf/repeated_field_reflection.h>
-
 #endif  // GOOGLE_PROTOBUF_REFLECTION_H__
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 4798eed..f5f5d3f 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -2264,7 +2264,7 @@
 
 // Iterators and helper functions that follow the spirit of the STL
 // std::back_insert_iterator and std::back_inserter but are tailor-made
-// for RepeatedField and RepatedPtrField. Typical usage would be:
+// for RepeatedField and RepeatedPtrField. Typical usage would be:
 //
 //   std::copy(some_sequence.begin(), some_sequence.end(),
 //             google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
index 8b82180..fcebe5c 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -410,6 +410,7 @@
   EXPECT_TRUE(mrf_message.empty());
 
 #ifdef PROTOBUF_HAS_DEATH_TEST
+
   // Make sure types are checked correctly at runtime.
   const FieldDescriptor* fd_optional_int32 =
       desc->FindFieldByName("optional_int32");
@@ -419,6 +420,7 @@
       message, fd_repeated_int32), "");
   EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>(
       message, fd_repeated_foreign_message), "");
+
 #endif  // PROTOBUF_HAS_DEATH_TEST
 }
 
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 15c0c93..66e7452 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -1131,7 +1131,7 @@
 
   string v = "f";
   RepeatedPtrField<string>::const_iterator it =
-      lower_bound(proto_array_.begin(), proto_array_.end(), v);
+      std::lower_bound(proto_array_.begin(), proto_array_.end(), v);
 
   EXPECT_EQ(*it, "n");
   EXPECT_TRUE(it == proto_array_.begin() + 3);
@@ -1292,8 +1292,8 @@
   {
     string v = "f";
     RepeatedPtrField<string>::pointer_iterator it =
-        lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
-                    &v, StringLessThan());
+        std::lower_bound(proto_array_.pointer_begin(),
+                         proto_array_.pointer_end(), &v, StringLessThan());
 
     GOOGLE_CHECK(*it != NULL);
 
@@ -1302,10 +1302,9 @@
   }
   {
     string v = "f";
-    RepeatedPtrField<string>::const_pointer_iterator it =
-        lower_bound(const_proto_array_->pointer_begin(),
-                    const_proto_array_->pointer_end(),
-                    &v, StringLessThan());
+    RepeatedPtrField<string>::const_pointer_iterator it = std::lower_bound(
+        const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(),
+        &v, StringLessThan());
 
     GOOGLE_CHECK(*it != NULL);
 
@@ -1343,9 +1342,8 @@
   EXPECT_EQ("foo", proto_array_.Get(0));
   EXPECT_EQ("n", proto_array_.Get(5));
   EXPECT_EQ("x", proto_array_.Get(9));
-  sort(proto_array_.pointer_begin(),
-       proto_array_.pointer_end(),
-       StringLessThan());
+  std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+            StringLessThan());
   EXPECT_EQ("a", proto_array_.Get(0));
   EXPECT_EQ("baz", proto_array_.Get(2));
   EXPECT_EQ("y", proto_array_.Get(9));
@@ -1478,9 +1476,9 @@
     new_data->set_bb(i);
   }
   TestAllTypes testproto;
-  copy(data.begin(), data.end(),
-       AllocatedRepeatedPtrFieldBackInserter(
-           testproto.mutable_repeated_nested_message()));
+  std::copy(data.begin(), data.end(),
+            AllocatedRepeatedPtrFieldBackInserter(
+                testproto.mutable_repeated_nested_message()));
   EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
 }
 
@@ -1497,9 +1495,8 @@
     *new_data = "name-" + SimpleItoa(i);
   }
   TestAllTypes testproto;
-  copy(data.begin(), data.end(),
-       AllocatedRepeatedPtrFieldBackInserter(
-           testproto.mutable_repeated_string()));
+  std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter(
+                                          testproto.mutable_repeated_string()));
   EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
 }
 
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
new file mode 100644
index 0000000..9f27eb4
--- /dev/null
+++ b/src/google/protobuf/struct.proto
@@ -0,0 +1,83 @@
+// 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 google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "StructProto";
+option java_package = "com.google.protobuf";
+
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+message Struct {
+  // Map of dynamically typed values.
+  map<string, Value> fields = 1;
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+message Value {
+  oneof kind {
+    // Represents a null value.
+    NullValue null_value = 1;
+    // Represents a double value.
+    double number_value = 2;
+    // Represents a string value.
+    string string_value = 3;
+    // Represents a boolean value.
+    bool bool_value = 4;
+    // Represents a structured value.
+    Struct struct_value = 5;
+    // Represents a repeated `Value`.
+    ListValue list_value = 6;
+  }
+}
+
+// `NullValue` is a singleton enumeration to represent the null
+// value for the `Value` type union.
+enum NullValue {
+  // Null value.
+  NULL_VALUE = 0;
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+message ListValue {
+  // Repeated field of dynamically typed values.
+  repeated Value values = 1;
+}
diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
index bbe2d84..36c1ec9 100644
--- a/src/google/protobuf/stubs/atomicops.h
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -207,6 +207,8 @@
 #include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
 #include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_TILE)
+#include <google/protobuf/stubs/atomicops_internals_tile_gcc.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) || defined(GOOGLE_PROTOBUF_ARCH_MIPS64)
 #include <google/protobuf/stubs/atomicops_internals_mips_gcc.h>
 #elif defined(__native_client__)
diff --git a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
index e3cd14c..f5837c9 100644
--- a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
+++ b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
@@ -65,7 +65,7 @@
                        "2:\n"
                        ".set pop\n"
                        : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
-                       : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+                       : "r" (old_value), "r" (new_value), "m" (*ptr)
                        : "memory");
   return prev;
 }
@@ -197,7 +197,7 @@
                        "2:\n"
                        ".set pop\n"
                        : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
-                       : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+                       : "r" (old_value), "r" (new_value), "m" (*ptr)
                        : "memory");
   return prev;
 }
diff --git a/src/google/protobuf/stubs/atomicops_internals_tile_gcc.h b/src/google/protobuf/stubs/atomicops_internals_tile_gcc.h
new file mode 100644
index 0000000..796d742
--- /dev/null
+++ b/src/google/protobuf/stubs/atomicops_internals_tile_gcc.h
@@ -0,0 +1,77 @@
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TILE_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TILE_GCC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+    asm volatile ("st4 %0, %1"
+                  : "=r" (*ptr)
+                  : "m" (value));
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+    Atomic32 dest;
+    asm volatile ("ld4s %0, %1"
+                  : "=r" (dest)
+                  : "m" (*ptr));
+    return dest;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+    asm volatile ("st %0, %1"
+                  : "=r" (*ptr)
+                  : "m" (value));
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+    Atomic64 dest;
+    asm volatile ("ld %0, %1"
+                  : "=r" (dest)
+                  : "m" (*ptr));
+    return dest;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+    return NoBarrier_Load(ptr);
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+    NoBarrier_Store(ptr, value);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+    Atomic64 tmp;
+    asm volatile ("mtspr CMPEXCH_VALUE, %3\n\t"
+                  "cmpexch %0, %1, %2"
+                  : "=r" (tmp), "=m" (*ptr)
+                  : "r" (new_value), "r" (old_value));
+    return tmp;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+    Atomic64 old_value;
+    asm volatile ("exch %0, %1, %2"
+                  : "=r" (old_value), "=m" (*ptr)
+                  : "r" (new_value));
+    return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 value) {
+    Atomic64 dest;
+    asm volatile ("fetchadd %0, %1, %2"
+                  : "=r" (dest), "=m" (*ptr)
+                  : "r" (value));
+    return *ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TILE_GCC_H_
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
old mode 100644
new mode 100755
index 5b6a073..82d5052
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -37,13 +37,14 @@
 
 #include <string.h>
 #include <google/protobuf/stubs/common.h>
-#include "config.h"
+#include <google/protobuf/stubs/pbconfig.h>
 
-#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
-#include HASH_MAP_H
-#include HASH_SET_H
+#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
+    defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
+#include GOOGLE_PROTOBUF_HASH_MAP_H
+#include GOOGLE_PROTOBUF_HASH_SET_H
 #else
-#define MISSING_HASH
+#define GOOGLE_PROTOBUF_MISSING_HASH
 #include <map>
 #include <set>
 #endif
@@ -51,7 +52,7 @@
 namespace google {
 namespace protobuf {
 
-#ifdef MISSING_HASH
+#ifdef GOOGLE_PROTOBUF_MISSING_HASH
 
 // This system doesn't have hash_map or hash_set.  Emulate them using map and
 // set.
@@ -88,15 +89,17 @@
 
 template <typename Key, typename Data,
           typename HashFcn = hash<Key>,
-          typename EqualKey = int >
-class hash_map : public std::map<Key, Data, HashFcn> {
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map : public std::map<Key, Data, HashFcn, EqualKey, Alloc> {
  public:
-  hash_map(int = 0) {}
+  hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
+           const Alloc& = Alloc()) {}
 };
 
 template <typename Key,
           typename HashFcn = hash<Key>,
-          typename EqualKey = int >
+          typename EqualKey = std::equal_to<Key> >
 class hash_set : public std::set<Key, HashFcn> {
  public:
   hash_set(int = 0) {}
@@ -105,7 +108,7 @@
 #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
 
 template <typename Key>
-struct hash : public HASH_NAMESPACE::hash_compare<Key> {
+struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<Key> {
 };
 
 // MSVC's hash_compare<const char*> hashes based on the string contents but
@@ -119,23 +122,26 @@
 
 template <>
 struct hash<const char*>
-  : public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
-};
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<
+        const char*, CstringLess> {};
 
 template <typename Key, typename Data,
           typename HashFcn = hash<Key>,
-          typename EqualKey = int >
-class hash_map : public HASH_NAMESPACE::hash_map<
-    Key, Data, HashFcn> {
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+          Key, Data, HashFcn, EqualKey, Alloc> {
  public:
-  hash_map(int = 0) {}
+  hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
+           const Alloc& = Alloc()) {}
 };
 
-template <typename Key,
-          typename HashFcn = hash<Key>,
-          typename EqualKey = int >
-class hash_set : public HASH_NAMESPACE::hash_set<
-    Key, HashFcn> {
+template <typename Key, typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key> >
+class hash_set
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+          Key, HashFcn, EqualKey> {
  public:
   hash_set(int = 0) {}
 };
@@ -143,7 +149,7 @@
 #else
 
 template <typename Key>
-struct hash : public HASH_NAMESPACE::hash<Key> {
+struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
 };
 
 template <typename Key>
@@ -168,23 +174,27 @@
 
 template <typename Key, typename Data,
           typename HashFcn = hash<Key>,
-          typename EqualKey = std::equal_to<Key> >
-class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
-    Key, Data, HashFcn, EqualKey> {
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+          Key, Data, HashFcn, EqualKey, Alloc> {
  public:
-  hash_map(int = 0) {}
+  hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
+           const Alloc& = Alloc()) {}
 };
 
-template <typename Key,
-          typename HashFcn = hash<Key>,
+template <typename Key, typename HashFcn = hash<Key>,
           typename EqualKey = std::equal_to<Key> >
-class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
-    Key, HashFcn, EqualKey> {
+class hash_set
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+          Key, HashFcn, EqualKey> {
  public:
   hash_set(int = 0) {}
 };
 
-#endif
+#undef GOOGLE_PROTOBUF_MISSING_HASH
+#endif  // !GOOGLE_PROTOBUF_MISSING_HASH
 
 template <>
 struct hash<string> {
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index 1ff09b8..0ab993f 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -52,6 +52,9 @@
 #elif defined(__ARMEL__)
 #define GOOGLE_PROTOBUF_ARCH_ARM 1
 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#elif defined(__tile__)
+#define GOOGLE_PROTOBUF_ARCH_TILE 1
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
 #elif defined(__aarch64__)
 #define GOOGLE_PROTOBUF_ARCH_AARCH64 1
 #define GOOGLE_PROTOBUF_ARCH_64_BIT 1
diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h
index e123e4f..9301f54 100644
--- a/src/google/protobuf/stubs/singleton.h
+++ b/src/google/protobuf/stubs/singleton.h
@@ -44,6 +44,10 @@
     GoogleOnceInit(&once_, &Singleton<T>::Init);
     return instance_;
   }
+  static void ShutDown() {
+    delete instance_;
+    instance_ = NULL;
+  }
  private:
   static void Init() {
     instance_ = new T();
@@ -56,7 +60,7 @@
 ProtobufOnceType Singleton<T>::once_;
 
 template<typename T>
-T* Singleton<T>::instance_;
+T* Singleton<T>::instance_ = NULL;
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 86d4568..7955d26 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -1303,6 +1303,211 @@
   return string(bufptr, buf + 16 - bufptr);
 }
 
+namespace strings {
+
+AlphaNum::AlphaNum(strings::Hex hex) {
+  char *const end = &digits[kFastToBufferSize];
+  char *writer = end;
+  uint64 value = hex.value;
+  uint64 width = hex.spec;
+  // We accomplish minimum width by OR'ing in 0x10000 to the user's value,
+  // where 0x10000 is the smallest hex number that is as wide as the user
+  // asked for.
+  uint64 mask = ((static_cast<uint64>(1) << (width - 1) * 4)) | value;
+  static const char hexdigits[] = "0123456789abcdef";
+  do {
+    *--writer = hexdigits[value & 0xF];
+    value >>= 4;
+    mask >>= 4;
+  } while (mask != 0);
+  piece_data_ = writer;
+  piece_size_ = end - writer;
+}
+
+}  // namespace strings
+
+// ----------------------------------------------------------------------
+// StrCat()
+//    This merges the given strings or integers, with no delimiter.  This
+//    is designed to be the fastest possible way to construct a string out
+//    of a mix of raw C strings, C++ strings, and integer values.
+// ----------------------------------------------------------------------
+
+// Append is merely a version of memcpy that returns the address of the byte
+// after the area just overwritten.  It comes in multiple flavors to minimize
+// call overhead.
+static char *Append1(char *out, const AlphaNum &x) {
+  memcpy(out, x.data(), x.size());
+  return out + x.size();
+}
+
+static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
+  memcpy(out, x1.data(), x1.size());
+  out += x1.size();
+
+  memcpy(out, x2.data(), x2.size());
+  return out + x2.size();
+}
+
+static char *Append4(char *out,
+                     const AlphaNum &x1, const AlphaNum &x2,
+                     const AlphaNum &x3, const AlphaNum &x4) {
+  memcpy(out, x1.data(), x1.size());
+  out += x1.size();
+
+  memcpy(out, x2.data(), x2.size());
+  out += x2.size();
+
+  memcpy(out, x3.data(), x3.size());
+  out += x3.size();
+
+  memcpy(out, x4.data(), x4.size());
+  return out + x4.size();
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b) {
+  string result;
+  result.resize(a.size() + b.size());
+  char *const begin = &*result.begin();
+  char *out = Append2(begin, a, b);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+  string result;
+  result.resize(a.size() + b.size() + c.size());
+  char *const begin = &*result.begin();
+  char *out = Append2(begin, a, b);
+  out = Append1(out, c);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append1(out, e);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append2(out, e, f);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size() + g.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append2(out, e, f);
+  out = Append1(out, g);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g, const AlphaNum &h) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size() + g.size() + h.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append4(out, e, f, g, h);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size() + g.size() + h.size() + i.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append4(out, e, f, g, h);
+  out = Append1(out, i);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+// It's possible to call StrAppend with a char * pointer that is partway into
+// the string we're appending to.  However the results of this are random.
+// Therefore, check for this in debug mode.  Use unsigned math so we only have
+// to do one comparison.
+#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \
+    GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \
+                     uintptr_t((dest).size()))
+
+void StrAppend(string *result, const AlphaNum &a) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  result->append(a.data(), a.size());
+}
+
+void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+  string::size_type old_size = result->size();
+  result->resize(old_size + a.size() + b.size());
+  char *const begin = &*result->begin();
+  char *out = Append2(begin + old_size, a, b);
+  GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+               const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+  string::size_type old_size = result->size();
+  result->resize(old_size + a.size() + b.size() + c.size());
+  char *const begin = &*result->begin();
+  char *out = Append2(begin + old_size, a, b);
+  out = Append1(out, c);
+  GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+               const AlphaNum &a, const AlphaNum &b,
+               const AlphaNum &c, const AlphaNum &d) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, d);
+  string::size_type old_size = result->size();
+  result->resize(old_size + a.size() + b.size() + c.size() + d.size());
+  char *const begin = &*result->begin();
+  char *out = Append4(begin + old_size, a, b, c, d);
+  GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
 int GlobalReplaceSubstring(const string& substring,
                            const string& replacement,
                            string* s) {
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index f2e1a94..920701e 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -495,57 +495,168 @@
 static const int kDoubleToBufferSize = 32;
 static const int kFloatToBufferSize = 24;
 
-// ----------------------------------------------------------------------
-// ToString() are internal help methods used in StrCat() and Join()
-// ----------------------------------------------------------------------
-namespace internal {
-inline string ToString(int i) {
-  return SimpleItoa(i);
-}
+namespace strings {
 
-inline string ToString(string a) {
-  return a;
-}
-}  // namespace internal
+struct Hex {
+  uint64 value;
+  enum PadSpec {
+    NONE = 1,
+    ZERO_PAD_2,
+    ZERO_PAD_3,
+    ZERO_PAD_4,
+    ZERO_PAD_5,
+    ZERO_PAD_6,
+    ZERO_PAD_7,
+    ZERO_PAD_8,
+    ZERO_PAD_9,
+    ZERO_PAD_10,
+    ZERO_PAD_11,
+    ZERO_PAD_12,
+    ZERO_PAD_13,
+    ZERO_PAD_14,
+    ZERO_PAD_15,
+    ZERO_PAD_16,
+  } spec;
+  template <class Int>
+  explicit Hex(Int v, PadSpec s = NONE)
+      : spec(s) {
+    // Prevent sign-extension by casting integers to
+    // their unsigned counterparts.
+#ifdef LANG_CXX11
+    static_assert(
+        sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
+        "Unknown integer type");
+#endif
+    value = sizeof(v) == 1 ? static_cast<uint8>(v)
+          : sizeof(v) == 2 ? static_cast<uint16>(v)
+          : sizeof(v) == 4 ? static_cast<uint32>(v)
+          : static_cast<uint64>(v);
+  }
+};
+
+struct AlphaNum {
+  const char *piece_data_;  // move these to string_ref eventually
+  size_t piece_size_;       // move these to string_ref eventually
+
+  char digits[kFastToBufferSize];
+
+  // No bool ctor -- bools convert to an integral type.
+  // A bool ctor would also convert incoming pointers (bletch).
+
+  AlphaNum(int32 i32)
+      : piece_data_(digits),
+        piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
+  AlphaNum(uint32 u32)
+      : piece_data_(digits),
+        piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
+  AlphaNum(int64 i64)
+      : piece_data_(digits),
+        piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
+  AlphaNum(uint64 u64)
+      : piece_data_(digits),
+        piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
+
+  AlphaNum(float f)
+    : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
+  AlphaNum(double f)
+    : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
+
+  AlphaNum(Hex hex);
+
+  AlphaNum(const char* c_str)
+      : piece_data_(c_str), piece_size_(strlen(c_str)) {}
+  // TODO: Add a string_ref constructor, eventually
+  // AlphaNum(const StringPiece &pc) : piece(pc) {}
+
+  AlphaNum(const string& str)
+      : piece_data_(str.data()), piece_size_(str.size()) {}
+
+  size_t size() const { return piece_size_; }
+  const char *data() const { return piece_data_; }
+
+ private:
+  // Use ":" not ':'
+  AlphaNum(char c);  // NOLINT(runtime/explicit)
+
+  // Disallow copy and assign.
+  AlphaNum(const AlphaNum&);
+  void operator=(const AlphaNum&);
+};
+
+}  // namespace strings
+
+using strings::AlphaNum;
 
 // ----------------------------------------------------------------------
 // StrCat()
-//    These methods join some strings together.
+//    This merges the given strings or numbers, with no delimiter.  This
+//    is designed to be the fastest possible way to construct a string out
+//    of a mix of raw C strings, strings, bool values,
+//    and numeric values.
+//
+//    Don't use this for user-visible strings.  The localization process
+//    works poorly on strings built up out of fragments.
+//
+//    For clarity and performance, don't use StrCat when appending to a
+//    string.  In particular, avoid using any of these (anti-)patterns:
+//      str.append(StrCat(...)
+//      str += StrCat(...)
+//      str = StrCat(str, ...)
+//    where the last is the worse, with the potential to change a loop
+//    from a linear time operation with O(1) dynamic allocations into a
+//    quadratic time operation with O(n) dynamic allocations.  StrAppend
+//    is a better choice than any of the above, subject to the restriction
+//    of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
+//    be a reference into str.
 // ----------------------------------------------------------------------
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
-          typename T6, typename T7>
-string StrCat(
-    const T1& a, const T2& b, const T3& c, const T4& d, const T5& e,
-    const T6& f, const T7& g) {
-  return internal::ToString(a) + internal::ToString(b) +
-      internal::ToString(c) + internal::ToString(d) + internal::ToString(e) +
-      internal::ToString(f) + internal::ToString(g);
-}
 
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-string StrCat(
-    const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) {
-  return internal::ToString(a) + internal::ToString(b) +
-      internal::ToString(c) + internal::ToString(d) + internal::ToString(e);
-}
+string StrCat(const AlphaNum &a, const AlphaNum &b);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g, const AlphaNum &h);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g, const AlphaNum &h, const AlphaNum &i);
 
-template <typename T1, typename T2, typename T3, typename T4>
-string StrCat(
-    const T1& a, const T2& b, const T3& c, const T4& d) {
-  return internal::ToString(a) + internal::ToString(b) +
-      internal::ToString(c) + internal::ToString(d);
-}
+inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }
 
-template <typename T1, typename T2, typename T3>
-string StrCat(const T1& a, const T2& b, const T3& c) {
-  return internal::ToString(a) + internal::ToString(b) +
-      internal::ToString(c);
-}
+// ----------------------------------------------------------------------
+// StrAppend()
+//    Same as above, but adds the output to the given string.
+//    WARNING: For speed, StrAppend does not try to check each of its input
+//    arguments to be sure that they are not a subset of the string being
+//    appended to.  That is, while this will work:
+//
+//    string s = "foo";
+//    s += s;
+//
+//    This will not (necessarily) work:
+//
+//    string s = "foo";
+//    StrAppend(&s, s);
+//
+//    Note: while StrCat supports appending up to 9 arguments, StrAppend
+//    is currently limited to 4.  That's rarely an issue except when
+//    automatically transforming StrCat to StrAppend, and can easily be
+//    worked around as consecutive calls to StrAppend are quite efficient.
+// ----------------------------------------------------------------------
 
-template <typename T1, typename T2>
-string StrCat(const T1& a, const T2& b) {
-  return internal::ToString(a) + internal::ToString(b);
-}
+void StrAppend(string* dest, const AlphaNum& a);
+void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b);
+void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b,
+               const AlphaNum& c);
+void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b,
+               const AlphaNum& c, const AlphaNum& d);
 
 // ----------------------------------------------------------------------
 // Join()
@@ -559,7 +670,7 @@
     if (it != start) {
       result->append(delim);
     }
-    result->append(internal::ToString(*it));
+    StrAppend(result, *it);
   }
 }
 
diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3
new file mode 100644
index 0000000..934f36f
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_proto3
Binary files differ
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 8e867c0..ec070c5 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -1360,9 +1360,8 @@
 bool TextFormat::Printer::RegisterFieldValuePrinter(
     const FieldDescriptor* field,
     const FieldValuePrinter* printer) {
-  return field != NULL
-      && printer != NULL
-      && custom_printers_.insert(make_pair(field, printer)).second;
+  return field != NULL && printer != NULL &&
+         custom_printers_.insert(std::make_pair(field, printer)).second;
 }
 
 bool TextFormat::Printer::PrintToString(const Message& message,
@@ -1422,7 +1421,7 @@
   vector<const FieldDescriptor*> fields;
   reflection->ListFields(message, &fields);
   if (print_message_fields_in_index_order_) {
-    sort(fields.begin(), fields.end(), FieldIndexSorter());
+    std::sort(fields.begin(), fields.end(), FieldIndexSorter());
   }
   for (int i = 0; i < fields.size(); i++) {
     PrintField(message, reflection, fields[i], generator);
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 44d68ca..9e2cb07 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -278,8 +278,20 @@
   };
 
   // Parses a text-format protocol message from the given input stream to
-  // the given message object.  This function parses the format written
-  // by Print().
+  // the given message object. This function parses the human-readable format
+  // written by Print(). Returns true on success. The message is cleared first,
+  // even if the function fails -- See Merge() to avoid this behavior.
+  //
+  // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}"
+  //
+  // One use for this function is parsing handwritten strings in test code.
+  // Another use is to parse the output from google::protobuf::Message::DebugString()
+  // (or ShortDebugString()), because these functions output using
+  // google::protobuf::TextFormat::Print().
+  //
+  // If you would like to read a protocol buffer serialized in the
+  // (non-human-readable) binary wire format, see
+  // google::protobuf::MessageLite::ParseFromString().
   static bool Parse(io::ZeroCopyInputStream* input, Message* output);
   // Like Parse(), but reads directly from a string.
   static bool ParseFromString(const string& input, Message* output);
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
new file mode 100644
index 0000000..ac8e009c
--- /dev/null
+++ b/src/google/protobuf/timestamp.proto
@@ -0,0 +1,103 @@
+// 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 google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "TimestampProto";
+option java_package = "com.google.protobuf";
+
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from  RFC 3339 date strings. (See https://www.ietf.org/rfc/rfc3339.txt.)
+//
+// Example 1: compute Timestamp from POSIX `time()`.
+//
+//     Timestamp timestamp;
+//     timestamp.set_seconds(time(NULL));
+//     timestamp.set_nanos(0);
+//
+// Example 2: compute Timestamp from POSIX `gettimeofday()`.
+//
+//     struct timeval tv;
+//     gettimeofday(&tv, NULL);
+//
+//     Timestamp timestamp;
+//     timestamp.set_seconds(tv.tv_sec);
+//     timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+//     FILETIME ft;
+//     GetSystemTimeAsFileTime(&ft);
+//     UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+//     // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+//     // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+//     Timestamp timestamp;
+//     timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+//     timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: compute Timestamp from Java `System.currentTimeMillis()`.
+//
+//     long millis = System.currentTimeMillis();
+//
+//     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+//         .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+// Example 5: compute Timestamp from Python `datetime.datetime`.
+//
+//     now = datetime.datetime.utcnow()
+//     seconds = int(time.mktime(now.timetuple()))
+//     nanos = now.microsecond * 1000
+//     timestamp = Timestamp(seconds=seconds, nanos=nanos)
+//
+message Timestamp {
+  // Represents seconds of UTC time since Unix epoch
+  // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+  // 9999-12-31T23:59:59Z inclusive.
+  int64 seconds = 1;
+
+  // Non-negative fractions of a second at nanosecond resolution. Negative
+  // second values with fractions must still have non-negative nanos values
+  // that count forward in time. Must be from 0 to 999,999,999
+  // inclusive.
+  int32 nanos = 2;
+}
diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
index 1a42083..36fb865 100644
--- a/src/google/protobuf/unittest_no_arena.proto
+++ b/src/google/protobuf/unittest_no_arena.proto
@@ -113,7 +113,7 @@
   optional protobuf_unittest_import.PublicImportMessage
       optional_public_import_message = 26;
 
-  optional NestedMessage optional_lazy_message = 27 [lazy=true];
+  optional NestedMessage optional_message = 27 [lazy=true];
 
   // Repeated
   repeated    int32 repeated_int32    = 31;
@@ -180,6 +180,7 @@
     NestedMessage oneof_nested_message = 112;
     string oneof_string = 113;
     bytes oneof_bytes = 114;
+    NestedMessage lazy_oneof_nested_message = 115 [lazy=true];
   }
 }
 
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
index ba050d7..67e5749 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -30,7 +30,7 @@
 
 syntax = "proto3";
 
-package proto2_preserve_unknown_enum_unittest;
+package proto3_preserve_unknown_enum_unittest;
 
 enum MyEnum {
   FOO = 0;
@@ -49,9 +49,10 @@
   optional MyEnum e = 1;
   repeated MyEnum repeated_e = 2;
   repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4;  // not packed
   oneof o {
-    MyEnum oneof_e_1 = 4;
-    MyEnum oneof_e_2 = 5;
+    MyEnum oneof_e_1 = 5;
+    MyEnum oneof_e_2 = 6;
   }
 }
 
@@ -59,8 +60,9 @@
   optional MyEnumPlusExtra e = 1;
   repeated MyEnumPlusExtra repeated_e = 2;
   repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true];
   oneof o {
-    MyEnumPlusExtra oneof_e_1 = 4;
-    MyEnumPlusExtra oneof_e_2 = 5;
+    MyEnumPlusExtra oneof_e_1 = 5;
+    MyEnumPlusExtra oneof_e_2 = 6;
   }
 }
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
new file mode 100644
index 0000000..adf4296
--- /dev/null
+++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
@@ -0,0 +1,50 @@
+// 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 = "proto2";
+
+package proto2_preserve_unknown_enum_unittest;
+
+enum MyEnum {
+  FOO = 0;
+  BAR = 1;
+  BAZ = 2;
+}
+
+message MyMessage {
+  optional MyEnum e = 1;
+  repeated MyEnum repeated_e = 2;
+  repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnum repeated_packed_unexpected_e = 4;  // not packed
+  oneof o {
+    MyEnum oneof_e_1 = 5;
+    MyEnum oneof_e_2 = 6;
+  }
+}
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
index 53f23d8..6d7bada 100644
--- a/src/google/protobuf/unittest_proto3_arena.proto
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -47,9 +47,10 @@
   }
 
   enum NestedEnum {
-    FOO = 0;
-    BAR = 1;
-    BAZ = 2;
+    ZERO = 0;
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
     NEG = -1;  // Intentionally negative.
   }
 
@@ -81,6 +82,11 @@
   optional NestedEnum                           optional_nested_enum     = 21;
   optional ForeignEnum                          optional_foreign_enum    = 22;
 
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // optional protobuf_unittest_import.ImportEnum    optional_import_enum  = 23;
+
   optional string optional_string_piece = 24 [ctype=STRING_PIECE];
   optional string optional_cord = 25 [ctype=CORD];
 
@@ -118,6 +124,11 @@
   repeated NestedEnum                           repeated_nested_enum     = 51;
   repeated ForeignEnum                          repeated_foreign_enum    = 52;
 
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // repeated protobuf_unittest_import.ImportEnum    repeated_import_enum  = 53;
+
   repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
   repeated string repeated_cord = 55 [ctype=CORD];
 
@@ -131,6 +142,31 @@
   }
 }
 
+// Test messages for packed fields
+
+message TestPackedTypes {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnum packed_enum  = 103 [packed = true];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  NestedTestAllTypes child = 1;
+  TestAllTypes payload = 2;
+}
+
 // Define these after TestAllTypes to make sure the compiler can handle
 // that.
 message ForeignMessage {
@@ -138,7 +174,13 @@
 }
 
 enum ForeignEnum {
-  FOREIGN_FOO = 0;
-  FOREIGN_BAR = 1;
-  FOREIGN_BAZ = 2;
+  FOREIGN_ZERO = 0;
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
 }
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
index fb5380a..39c10cb 100644
--- a/src/google/protobuf/unknown_enum_impl.h
+++ b/src/google/protobuf/unknown_enum_impl.h
@@ -99,6 +99,29 @@
 }
 
 // NOTE: You should not call these functions directly.  Instead use
+// CLEAR_UNKNOWN_ENUM(), defined in the public header.  The macro-versions
+// operate in a type-safe manner and behave appropriately for the proto
+// version of the message, whereas these versions assume a specific proto
+// version and allow the caller to pass in any arbitrary integer value as a
+// field number.
+//
+// Clears the unknown entries of the given field of the message.
+void ClearUnknownEnum(Message* message, int32 field_number);
+// In proto1, clears the field if the value is out of range.
+// TODO(karner): Delete this or make it proto2-only once the migration
+// to proto2 is complete.
+void ClearUnknownEnumProto1(Message* message, int32 field_number);
+template <typename T>
+void ClearUnknownEnum_Template(T* message, int32 field_number) {
+  if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
+      !internal::is_base_of<ProtocolMessage, T>::value) {
+    ClearUnknownEnum(message, field_number);
+  } else {
+    ClearUnknownEnumProto1(message, field_number);
+  }
+}
+
+// NOTE: You should not call these functions directly.  Instead use
 // SET_UNKNOWN_ENUM(), defined in the public header.  The macro-versions
 // operate in a type-safe manner and behave appropriately for the proto
 // version of the message, whereas these versions assume a specific proto
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index e8c0a13..987b197 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -222,13 +222,12 @@
   // UnknownField is being created.
   inline void SetType(Type type);
 
-  uint32 number_;
-  uint32 type_;
-
   union LengthDelimited {
     string* string_value_;
   };
 
+  uint32 number_;
+  uint32 type_;
   union {
     uint64 varint_;
     uint32 fixed32_;
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index f4f0215..c5bbbf2 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -141,7 +141,7 @@
 
 bool WireFormat::SkipMessage(io::CodedInputStream* input,
                              UnknownFieldSet* unknown_fields) {
-  while(true) {
+  while (true) {
     uint32 tag = input->ReadTag();
     if (tag == 0) {
       // End of input.  This is a valid place to end, so return true.
@@ -159,6 +159,31 @@
   }
 }
 
+bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+                                                uint32 field_number,
+                                                bool (*is_valid)(int),
+                                                UnknownFieldSet* unknown_fields,
+                                                RepeatedField<int>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  while (input->BytesUntilLimit() > 0) {
+    int value;
+    if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+        int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+      return false;
+    }
+    if (is_valid == NULL || is_valid(value)) {
+      values->Add(value);
+    } else {
+      unknown_fields->AddVarint(field_number, value);
+    }
+  }
+  input->PopLimit(limit);
+  return true;
+}
+
+
 void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
                                         io::CodedOutputStream* output) {
   for (int i = 0; i < unknown_fields.field_count(); i++) {
@@ -520,6 +545,14 @@
                 field->enum_type()->FindValueByNumber(value);
             if (enum_value != NULL) {
               message_reflection->AddEnum(message, field, enum_value);
+            } else {
+              // The enum value is not one of the known values.  Add it to the
+              // UnknownFieldSet.
+              int64 sign_extended_value = static_cast<int64>(value);
+              message_reflection->MutableUnknownFields(message)
+                  ->AddVarint(
+                      WireFormatLite::GetTagFieldNumber(tag),
+                      sign_extended_value);
             }
           }
         }
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 9f26eb2..8de491a 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -138,6 +138,14 @@
   static bool SkipMessage(io::CodedInputStream* input,
                           UnknownFieldSet* unknown_fields);
 
+  // Read a packed enum field. If the is_valid function is not NULL, values for
+  // which is_valid(value) returns false are appended to unknown_fields_stream.
+  static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+                                             uint32 field_number,
+                                             bool (*is_valid)(int),
+                                             UnknownFieldSet* unknown_fields,
+                                             RepeatedField<int>* values);
+
   // Write the contents of an UnknownFieldSet to the output.
   static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
                                      io::CodedOutputStream* output);
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 5061655..2ce4920 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -304,6 +304,34 @@
   return true;
 }
 
+bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
+    io::CodedInputStream* input,
+    int field_number,
+    bool (*is_valid)(int),
+    io::CodedOutputStream* unknown_fields_stream,
+    RepeatedField<int>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  while (input->BytesUntilLimit() > 0) {
+    int value;
+    if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+        int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+      return false;
+    }
+    if (is_valid == NULL || is_valid(value)) {
+      values->Add(value);
+    } else {
+      uint32 tag = WireFormatLite::MakeTag(field_number,
+                                           WireFormatLite::WIRETYPE_VARINT);
+      unknown_fields_stream->WriteVarint32(tag);
+      unknown_fields_stream->WriteVarint32(value);
+    }
+  }
+  input->PopLimit(limit);
+  return true;
+}
+
 void WireFormatLite::WriteInt32(int field_number, int32 value,
                                 io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_VARINT, output);
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index acf88ea..76bc75a 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -291,11 +291,20 @@
   template <typename CType, enum FieldType DeclaredType>
   static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
 
-  // Read a packed enum field. Values for which is_valid() returns false are
-  // dropped. If is_valid == NULL, no values are dropped.
+  // Read a packed enum field. If the is_valid function is not NULL, values for
+  // which is_valid(value) returns false are silently dropped.
   static bool ReadPackedEnumNoInline(input,
                                      bool (*is_valid)(int),
-                                     RepeatedField<int>* value);
+                                     RepeatedField<int>* values);
+
+  // Read a packed enum field. If the is_valid function is not NULL, values for
+  // which is_valid(value) returns false are appended to unknown_fields_stream.
+  static bool ReadPackedEnumPreserveUnknowns(
+      input,
+      field_number,
+      bool (*is_valid)(int),
+      io::CodedOutputStream* unknown_fields_stream,
+      RepeatedField<int>* values);
 
   // Read a string.  ReadString(..., string* value) requires an existing string.
   static inline bool ReadString(input, string* value);
@@ -647,7 +656,7 @@
 
 inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
   // Note:  the right-shift must be arithmetic
-  return (n << 1) ^ (n >> 31);
+  return (static_cast<uint32>(n) << 1) ^ (n >> 31);
 }
 
 inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
@@ -656,7 +665,7 @@
 
 inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
   // Note:  the right-shift must be arithmetic
-  return (n << 1) ^ (n >> 63);
+  return (static_cast<uint64>(n) << 1) ^ (n >> 63);
 }
 
 inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
new file mode 100644
index 0000000..5164c24
--- /dev/null
+++ b/src/google/protobuf/wrappers.proto
@@ -0,0 +1,97 @@
+// 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.
+
+// Wrappers for primitive (non-message) types. These types are useful
+// for embedding primitives in the `google.protobuf.Any` type and for places
+// where we need to distinguish between the absence of a primitive
+// typed field and its default value.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "WrappersProto";
+option java_package = "com.google.protobuf";
+
+
+// Wrapper message for double.
+message DoubleValue {
+  // The double value.
+  double value = 1;
+}
+
+// Wrapper message for float.
+message FloatValue {
+  // The float value.
+  float value = 1;
+}
+
+// Wrapper message for int64.
+message Int64Value {
+  // The int64 value.
+  int64 value = 1;
+}
+
+// Wrapper message for uint64.
+message UInt64Value {
+  // The uint64 value.
+  uint64 value = 1;
+}
+
+// Wrapper message for int32.
+message Int32Value {
+  // The int32 value.
+  int32 value = 1;
+}
+
+// Wrapper message for uint32.
+message UInt32Value {
+  // The uint32 value.
+  uint32 value = 1;
+}
+
+// Wrapper message for bool.
+message BoolValue {
+  // The bool value.
+  bool value = 1;
+}
+
+// Wrapper message for string.
+message StringValue {
+  // The string value.
+  string value = 1;
+}
+
+// Wrapper message for bytes.
+message BytesValue {
+  // The bytes value.
+  bytes value = 1;
+}
diff --git a/vsprojects/config.h b/vsprojects/config.h
old mode 100644
new mode 100755
index 2c64450..a93bb03
--- a/vsprojects/config.h
+++ b/vsprojects/config.h
@@ -1,28 +1,19 @@
 /* protobuf config.h for MSVC.  On other platforms, this is generated
  * automatically by autoheader / autoconf / configure. */
 
-/* the location of <hash_map> */
-#define HASH_MAP_H <hash_map>
+#include <google/protobuf/stubs/pbconfig.h>
 
-/* the namespace of hash_map/hash_set */
-// Apparently Microsoft decided to move hash_map *back* to the std namespace
-// in MSVC 2010:
-//   http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
-// TODO(kenton):  Use unordered_map instead, which is available in MSVC 2010.
-#if _MSC_VER < 1310 || _MSC_VER >= 1600
-#define HASH_NAMESPACE std
-#else
-#define HASH_NAMESPACE stdext
+#define HASH_MAP_H GOOGLE_PROTOBUF_HASH_MAP_H
+#define HASH_NAMESPACE GOOGLE_PROTOBUF_HASH_NAMESPACE
+#define HASH_SET_H GOOGLE_PROTOBUF_HASH_SET_H
+
+#ifdef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+#define HAVE_HASH_MAP GOOGLE_PROTOBUF_HAVE_HASH_MAP
 #endif
 
-/* the location of <hash_set> */
-#define HASH_SET_H <hash_set>
-
-/* define if the compiler has hash_map */
-#define HAVE_HASH_MAP 1
-
-/* define if the compiler has hash_set */
-#define HAVE_HASH_SET 1
+#ifdef GOOGLE_PROTOBUF_HAVE_HASH_SET
+#define HAVE_HASH_SET GOOGLE_PROTOBUF_HAVE_HASH_SET
+#endif
 
 /* define if you want to use zlib.  See readme.txt for additional
  * requirements. */
diff --git a/vsprojects/extract_includes.bat b/vsprojects/extract_includes.bat
index 587c1a8..ddf7f33 100755
--- a/vsprojects/extract_includes.bat
+++ b/vsprojects/extract_includes.bat
@@ -6,7 +6,9 @@
 md include\google\protobuf\compiler
 md include\google\protobuf\compiler\cpp
 md include\google\protobuf\compiler\java
+md include\google\protobuf\compiler\javanano
 md include\google\protobuf\compiler\python
+md include\google\protobuf\compiler\ruby
 copy ..\src\google\protobuf\arena.h include\google\protobuf\arena.h
 copy ..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h
 copy ..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h
@@ -14,16 +16,19 @@
 copy ..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
 copy ..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
 copy ..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
+copy ..\src\google\protobuf\compiler\javanano\javanano_generator.h include\google\protobuf\compiler\javanano\javanano_generator.h
 copy ..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
 copy ..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
 copy ..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h
 copy ..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
+copy ..\src\google\protobuf\compiler\ruby\ruby_generator.h include\google\protobuf\compiler\ruby\ruby_generator.h
 copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
 copy ..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h
 copy ..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h
 copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h
 copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h
 copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h
+copy ..\src\google\protobuf\generated_enum_util.h include\google\protobuf\generated_enum_util.h
 copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h
 copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
 copy ..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h
@@ -35,7 +40,9 @@
 copy ..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h
 copy ..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h
 copy ..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h
+copy ..\src\google\protobuf\map_entry_lite.h include\google\protobuf\map_entry_lite.h
 copy ..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h
+copy ..\src\google\protobuf\map_field_lite.h include\google\protobuf\map_field_lite.h
 copy ..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h
 copy ..\src\google\protobuf\map.h include\google\protobuf\map.h
 copy ..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h
@@ -68,6 +75,7 @@
 copy ..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
 copy ..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
 copy ..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h
+copy ..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h
 copy ..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h
 copy ..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
 copy ..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
@@ -76,3 +84,4 @@
 copy ..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h
 copy ..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h
 copy ..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h
+copy google\protobuf\stubs\pbconfig.h include\google\protobuf\stubs\pbconfig.h
diff --git a/vsprojects/google/protobuf/stubs/pbconfig.h b/vsprojects/google/protobuf/stubs/pbconfig.h
new file mode 100755
index 0000000..18250a2
--- /dev/null
+++ b/vsprojects/google/protobuf/stubs/pbconfig.h
@@ -0,0 +1,39 @@
+/* protobuf config.h for MSVC.  On other platforms, this is generated
+ * automatically by autoheader / autoconf / configure. */
+
+// NOTE: if you add new macros in this file manually, please propagate the macro
+// to vsprojects/config.h.
+
+/* the namespace of hash_map/hash_set */
+// Apparently Microsoft decided to move hash_map *back* to the std namespace
+// in MSVC 2010:
+//   http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
+// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
+// said, use unordered_map for MSVC 2010 and beyond is our safest bet.
+#if _MSC_VER >= 1600
+#define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+#define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map>
+#define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
+#define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set>
+#define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
+#elif _MSC_VER >= 1310
+#define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
+#define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map>
+#define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#define GOOGLE_PROTOBUF_HASH_SET_H <hash_set>
+#define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#else
+#define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+#define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map>
+#define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#define GOOGLE_PROTOBUF_HASH_SET_H <hash_set>
+#define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#endif
+
+/* the location of <hash_set> */
+
+/* define if the compiler has hash_map */
+#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
+
+/* define if the compiler has hash_set */
+#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
diff --git a/vsprojects/libprotobuf-lite.vcproj b/vsprojects/libprotobuf-lite.vcproj
index 09eca4d..d245448 100644
--- a/vsprojects/libprotobuf-lite.vcproj
+++ b/vsprojects/libprotobuf-lite.vcproj
@@ -164,6 +164,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\google\protobuf\stubs\pbconfig.h"
+				>
+			</File>
+			<File
 				RelativePath="..\src\google\protobuf\extension_set.h"
 				>
 			</File>
@@ -179,6 +183,9 @@
 				RelativePath="..\src\google\protobuf\stubs\map-util.h"
 				>
 			</File>
+			<File RelativePath="..\src\google\protobuf\generated_enum_util.h"></File>
+			<File RelativePath="..\src\google\protobuf\map_entry_lite.h"></File>
+			<File RelativePath="..\src\google\protobuf\map_field_lite.h"></File>
 			<File
 				RelativePath="..\src\google\protobuf\message_lite.h"
 				>
diff --git a/vsprojects/libprotobuf.vcproj b/vsprojects/libprotobuf.vcproj
index 095d394..e782885 100644
--- a/vsprojects/libprotobuf.vcproj
+++ b/vsprojects/libprotobuf.vcproj
@@ -164,6 +164,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\google\protobuf\stubs\pbconfig.h"
+				>
+			</File>
+			<File
 				RelativePath="..\src\google\protobuf\descriptor.h"
 				>
 			</File>
@@ -219,6 +223,9 @@
 				RelativePath="..\src\google\protobuf\message_lite.h"
 				>
 			</File>
+			<File RelativePath="..\src\google\protobuf\generated_enum_util.h"></File>
+			<File RelativePath="..\src\google\protobuf\map_entry_lite.h"></File>
+			<File RelativePath="..\src\google\protobuf\map_field_lite.h"></File>
 			<File
 				RelativePath="..\src\google\protobuf\stubs\atomicops.h"
 			>
diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj
index 45a5936..455c2cc 100644
--- a/vsprojects/libprotoc.vcproj
+++ b/vsprojects/libprotoc.vcproj
@@ -1,518 +1,542 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="libprotoc"
-	ProjectGUID="{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}"
-	Keyword="Win32Proj"
-	TargetFrameworkVersion="0"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="Debug"
-			IntermediateDirectory="$(OutDir)\$(ProjectName)"
-			ConfigurationType="4"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
-				Optimization="0"
-				AdditionalIncludeDirectories="../src;."
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="Release"
-			IntermediateDirectory="$(OutDir)\$(ProjectName)"
-			ConfigurationType="4"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
-				AdditionalIncludeDirectories="../src;."
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
-				RuntimeLibrary="2"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
-			>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\code_generator.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\command_line_interface.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\subprocess.h"
-				>
-			</File>
+  ProjectType="Visual C++"
+  Version="9.00"
+  Name="libprotoc"
+  ProjectGUID="{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}"
+  Keyword="Win32Proj"
+  TargetFrameworkVersion="0"
+  >
+  <Platforms>
+    <Platform
+      Name="Win32"
+    />
+  </Platforms>
+  <ToolFiles>
+  </ToolFiles>
+  <Configurations>
+    <Configuration
+      Name="Debug|Win32"
+      OutputDirectory="Debug"
+      IntermediateDirectory="$(OutDir)\$(ProjectName)"
+      ConfigurationType="4"
+      >
+      <Tool
+        Name="VCPreBuildEventTool"
+      />
+      <Tool
+        Name="VCCustomBuildTool"
+      />
+      <Tool
+        Name="VCXMLDataGeneratorTool"
+      />
+      <Tool
+        Name="VCWebServiceProxyGeneratorTool"
+      />
+      <Tool
+        Name="VCMIDLTool"
+      />
+      <Tool
+        Name="VCCLCompilerTool"
+        AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+        Optimization="0"
+        AdditionalIncludeDirectories="../src;."
+        PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
+        MinimalRebuild="true"
+        BasicRuntimeChecks="3"
+        RuntimeLibrary="3"
+        UsePrecompiledHeader="0"
+        WarningLevel="3"
+        Detect64BitPortabilityProblems="true"
+        DebugInformationFormat="4"
+      />
+      <Tool
+        Name="VCManagedResourceCompilerTool"
+      />
+      <Tool
+        Name="VCResourceCompilerTool"
+      />
+      <Tool
+        Name="VCPreLinkEventTool"
+      />
+      <Tool
+        Name="VCLibrarianTool"
+      />
+      <Tool
+        Name="VCALinkTool"
+      />
+      <Tool
+        Name="VCXDCMakeTool"
+      />
+      <Tool
+        Name="VCBscMakeTool"
+      />
+      <Tool
+        Name="VCFxCopTool"
+      />
+      <Tool
+        Name="VCPostBuildEventTool"
+      />
+    </Configuration>
+    <Configuration
+      Name="Release|Win32"
+      OutputDirectory="Release"
+      IntermediateDirectory="$(OutDir)\$(ProjectName)"
+      ConfigurationType="4"
+      >
+      <Tool
+        Name="VCPreBuildEventTool"
+      />
+      <Tool
+        Name="VCCustomBuildTool"
+      />
+      <Tool
+        Name="VCXMLDataGeneratorTool"
+      />
+      <Tool
+        Name="VCWebServiceProxyGeneratorTool"
+      />
+      <Tool
+        Name="VCMIDLTool"
+      />
+      <Tool
+        Name="VCCLCompilerTool"
+        AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+        AdditionalIncludeDirectories="../src;."
+        PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
+        RuntimeLibrary="2"
+        UsePrecompiledHeader="0"
+        WarningLevel="3"
+        Detect64BitPortabilityProblems="true"
+        DebugInformationFormat="3"
+      />
+      <Tool
+        Name="VCManagedResourceCompilerTool"
+      />
+      <Tool
+        Name="VCResourceCompilerTool"
+      />
+      <Tool
+        Name="VCPreLinkEventTool"
+      />
+      <Tool
+        Name="VCLibrarianTool"
+      />
+      <Tool
+        Name="VCALinkTool"
+      />
+      <Tool
+        Name="VCXDCMakeTool"
+      />
+      <Tool
+        Name="VCBscMakeTool"
+      />
+      <Tool
+        Name="VCFxCopTool"
+      />
+      <Tool
+        Name="VCPostBuildEventTool"
+      />
+    </Configuration>
+  </Configurations>
+  <References>
+  </References>
+  <Files>
+    <Filter
+      Name="Header Files"
+      Filter="h;hpp;hxx;hm;inl;inc;xsd"
+      UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+      >
+      <File
+        RelativePath="..\src\google\protobuf\compiler\code_generator.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\command_line_interface.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\subprocess.h"
+        >
+      </File>
       <File
         RelativePath="..\src\google\protobuf\compiler\zip_writer.h"
         >
       </File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\plugin.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\plugin.pb.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_options.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_context.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_enum.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_extension.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_file.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_generator.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_helpers.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_message.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_message_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_service.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_string_field.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.h"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\python\python_generator.h"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
-			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
-			>
-		</Filter>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
-			>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\code_generator.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\command_line_interface.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_context.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_extension.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_file.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_generator.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_helpers.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_message_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_service.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\java\java_string_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\plugin.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\python\python_generator.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\subprocess.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"
-				>
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\plugin.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\plugin.pb.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_options.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_context.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_enum.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_extension.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_file.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_generator.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_helpers.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_message.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_message_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_service.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_string_field.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
+        >
+      </File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_map_field.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_params.h"></File>
+      <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.h"></File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\python\python_generator.h"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.h"
+        >
+      </File>
+    </Filter>
+    <Filter
+      Name="Resource Files"
+      Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+      UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+      >
+    </Filter>
+    <Filter
+      Name="Source Files"
+      Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+      UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+      >
+      <File
+        RelativePath="..\src\google\protobuf\compiler\code_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\command_line_interface.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_context.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_extension.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_file.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_helpers.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_message_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_service.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\java\java_string_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_map_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\plugin.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\python\python_generator.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\subprocess.cc"
+        >
+      </File>
+      <File
+        RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"
+        >
+      </File>
+    </Filter>
+  </Files>
+  <Globals>
+  </Globals>
 </VisualStudioProject>
diff --git a/vsprojects/lite-test.vcproj b/vsprojects/lite-test.vcproj
index bb33809..8d17224 100644
--- a/vsprojects/lite-test.vcproj
+++ b/vsprojects/lite-test.vcproj
@@ -182,6 +182,8 @@
 				RelativePath="..\src\google\protobuf\test_util_lite.h"
 				>
 			</File>
+			<File RelativePath=".\google\protobuf\map_lite_unittest.pb.h"></File>
+			<File RelativePath="..\src\google\protobuf\map_lite_test_util.h"></File>
 			<File
 				RelativePath=".\google\protobuf\unittest_lite.pb.h"
 				>
@@ -218,6 +220,8 @@
 				RelativePath=".\google\protobuf\unittest_lite.pb.cc"
 				>
 			</File>
+			<File RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"></File>
+			<File RelativePath="..\src\google\protobuf\map_lite_test_util.cc"></File>
 			<File
 				RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"
 				>
@@ -299,6 +303,30 @@
 				/>
 			</FileConfiguration>
 		</File>
+		<File
+			RelativePath="..\src\google\protobuf\map_lite_unittest.proto"
+			>
+			<FileConfiguration
+				Name="Debug|Win32"
+				>
+				<Tool
+					Name="VCCustomBuildTool"
+					Description="Generating map_lite_unittest.pb.{h,cc}..."
+					CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto&#x0D;&#x0A;"
+					Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+				/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Release|Win32"
+				>
+				<Tool
+					Name="VCCustomBuildTool"
+					Description="Generating map_lite_unittest.pb.{h,cc}..."
+					CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto&#x0D;&#x0A;"
+					Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+				/>
+			</FileConfiguration>
+		</File>
 	</Files>
 	<Globals>
 	</Globals>
diff --git a/vsprojects/tests.vcproj b/vsprojects/tests.vcproj
index 23c81f0..0d42949 100644
--- a/vsprojects/tests.vcproj
+++ b/vsprojects/tests.vcproj
@@ -194,6 +194,9 @@
 				RelativePath="..\src\google\protobuf\test_util.h"
 				>
 			</File>
+			<File RelativePath="..\src\google\protobuf\map_test_util_impl.h"></File>
+			<File RelativePath="..\src\google\protobuf\map_test_util.h"></File>
+			<File RelativePath="..\src\google\protobuf\arena_test_util.h"></File>
 			<File
 				RelativePath="..\src\google\protobuf\compiler\mock_code_generator.h"
 				>
@@ -346,6 +349,7 @@
 				RelativePath="..\src\google\protobuf\map_test_util.cc"
 				>
 			</File>
+			<File RelativePath="..\src\google\protobuf\arena_test_util.cc"></File>
 			<File
 				RelativePath="..\src\google\protobuf\message_unittest.cc"
 				>
@@ -431,7 +435,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"
+				RelativePath=".\google\protobuf\unittest_preserve_unknown_enum2.pb.cc"
 				>
 			</File>
 			<File
@@ -524,16 +528,16 @@
 			</File>
 		</Filter>
 		<File
-			RelativePath="..\src\google\protobuf\map_lite_unittest.proto"
+			RelativePath="..\src\google\protobuf\unittest_preserve_unknown_enum2.proto"
 			>
 			<FileConfiguration
 				Name="Debug|Win32"
 				>
 				<Tool
 					Name="VCCustomBuildTool"
-					Description="Generating map_lite_unittest.pb.{h,cc}..."
-					CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto"
-					Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+					Description="Generating unittest_preserve_unknown_enum2.pb.{h,cc}..."
+					CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum2.proto"
+					Outputs="google\protobuf\unittest_preserve_unknown_enum2.pb.h;google\protobuf\unittest_preserve_unknown_enum2.pb.cc"
 				/>
 			</FileConfiguration>
 			<FileConfiguration
@@ -541,9 +545,9 @@
 				>
 				<Tool
 					Name="VCCustomBuildTool"
-					Description="Generating map_lite_unittest.pb.{h,cc}..."
-					CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto"
-					Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+					Description="Generating unittest_preserve_unknown_enum2.pb.{h,cc}..."
+					CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum2.proto"
+					Outputs="google\protobuf\unittest_preserve_unknown_enum2.pb.h;google\protobuf\unittest_preserve_unknown_enum2.pb.cc"
 				/>
 			</FileConfiguration>
 		</File>