Submit recent changes from internal branch, including "lite mode" for
C++ and Java.  See CHANGES.txt for more details.

diff --git a/CHANGES.txt b/CHANGES.txt
index 4f870c3..c7e5bc9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,9 @@
-????-??-?? version 2.1.1:
+????-??-?? version 2.2.0:
 
   C++
+  * Lite mode:  The "optimize_for = LITE_RUNTIME" option causes the compiler
+    to generate code which only depends libprotobuf-lite, which is much smaller
+    than libprotobuf but lacks descriptors, reflection, and some other features.
   * Fixed bug where Message.Swap(Message) was only implemented for
     optimize_for_speed.  Swap now properly implemented in both modes
     (Issue 91).
@@ -10,6 +13,27 @@
   * Floating-point literals in generated code that are intended to be
     single-precision now explicitly have 'f' suffix to avoid pedantic warnings
     produced by some compilers.
+  * The [deprecated=true] option now causes the C++ code generator to generate
+    a GCC-style deprecation annotation (no-op on other compilers).
+  * google::protobuf::GetEnumDescriptor<SomeGeneratedEnumType>() returns the
+    EnumDescriptor for that type -- useful for templates which cannot call
+    SomeGeneratedEnumType_descriptor().
+  * Various optimizations and obscure bug fixes.
+
+  Java
+  * Lite mode:  The "optimize_for = LITE_RUNTIME" option causes the compiler
+    to generate code which only depends libprotobuf-lite, which is much smaller
+    than libprotobuf but lacks descriptors, reflection, and some other features.
+  * Put Builder objects on a freelist after build() is called, so they may be
+    reused later.
+  * Lots of style cleanups.
+
+  Python
+  * Fixed endianness bug with floats and doubles.
+  * Text format parsing support.
+  * Fix bug with parsing packed repeated fields in embedded messages.
+  * Ability to initialize fields by passing keyword args to constructor.
+  * Support iterators in extend and __setslice__ for containers.
 
 2009-05-13 version 2.1.0:
 
diff --git a/Makefile.am b/Makefile.am
index c6412d8..d3ed37c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -62,6 +62,7 @@
   examples/add_person.py                                                     \
   examples/list_people.py                                                    \
   java/src/main/java/com/google/protobuf/AbstractMessage.java                \
+  java/src/main/java/com/google/protobuf/AbstractMessageLite.java            \
   java/src/main/java/com/google/protobuf/BlockingRpcChannel.java             \
   java/src/main/java/com/google/protobuf/BlockingService.java                \
   java/src/main/java/com/google/protobuf/ByteString.java                     \
@@ -70,10 +71,14 @@
   java/src/main/java/com/google/protobuf/Descriptors.java                    \
   java/src/main/java/com/google/protobuf/DynamicMessage.java                 \
   java/src/main/java/com/google/protobuf/ExtensionRegistry.java              \
+  java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java          \
   java/src/main/java/com/google/protobuf/FieldSet.java                       \
   java/src/main/java/com/google/protobuf/GeneratedMessage.java               \
+  java/src/main/java/com/google/protobuf/GeneratedMessageLite.java           \
+  java/src/main/java/com/google/protobuf/Internal.java                       \
   java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
   java/src/main/java/com/google/protobuf/Message.java                        \
+  java/src/main/java/com/google/protobuf/MessageLite.java                    \
   java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java            \
   java/src/main/java/com/google/protobuf/RpcCallback.java                    \
   java/src/main/java/com/google/protobuf/RpcChannel.java                     \
@@ -91,6 +96,7 @@
   java/src/test/java/com/google/protobuf/DescriptorsTest.java                \
   java/src/test/java/com/google/protobuf/DynamicMessageTest.java             \
   java/src/test/java/com/google/protobuf/GeneratedMessageTest.java           \
+  java/src/test/java/com/google/protobuf/LiteTest.java                       \
   java/src/test/java/com/google/protobuf/MessageTest.java                    \
   java/src/test/java/com/google/protobuf/ServiceTest.java                    \
   java/src/test/java/com/google/protobuf/TestUtil.java                       \
@@ -110,6 +116,7 @@
   python/google/protobuf/internal/input_stream.py                            \
   python/google/protobuf/internal/input_stream_test.py                       \
   python/google/protobuf/internal/message_listener.py                        \
+  python/google/protobuf/internal/message_test.py                            \
   python/google/protobuf/internal/more_extensions.proto                      \
   python/google/protobuf/internal/more_messages.proto                        \
   python/google/protobuf/internal/output_stream.py                           \
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index 548b2e8..69dd7da 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -5,6 +5,10 @@
 # itself, they cannot be generated automatically by a make rule.  "make check"
 # will fail if these files do not match what the protocol compiler would
 # generate.
+#
+# HINT:  Flags passed to generate_descriptor_proto.sh will be passed directly
+#   to make when building protoc.  This is particularly useful for passing
+#   -j4 to run 4 jobs simultaneously.
 
 if test ! -e src/google/protobuf/stubs/common.h; then
   cat >&2 << __EOF__
@@ -23,5 +27,5 @@
 fi
 
 cd src
-make protoc && ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto
+make $@ protoc && ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto
 cd ..
diff --git a/java/pom.xml b/java/pom.xml
index 12787a4..bf5d206 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -124,6 +124,9 @@
                     value="../src/google/protobuf/unittest_optimize_for.proto" />
                   <arg
                     value="../src/google/protobuf/unittest_custom_options.proto" />
+                  <arg value="../src/google/protobuf/unittest_lite.proto" />
+                  <arg value="../src/google/protobuf/unittest_import_lite.proto" />
+                  <arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
                 </exec>
               </tasks>
               <testSourceRoot>target/generated-test-sources</testSourceRoot>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index 53175cd..e5bdefe 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -30,12 +30,12 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 
-import java.io.FilterInputStream;
 import java.io.InputStream;
 import java.io.IOException;
-import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -45,11 +45,12 @@
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class AbstractMessage implements Message {
+public abstract class AbstractMessage extends AbstractMessageLite
+                                      implements Message {
   @SuppressWarnings("unchecked")
   public boolean isInitialized() {
     // Check that all required fields are present.
-    for (FieldDescriptor field : getDescriptorForType().getFields()) {
+    for (final FieldDescriptor field : getDescriptorForType().getFields()) {
       if (field.isRequired()) {
         if (!hasField(field)) {
           return false;
@@ -58,11 +59,12 @@
     }
 
     // Check that embedded messages are initialized.
-    for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
-      FieldDescriptor field = entry.getKey();
+    for (final Map.Entry<FieldDescriptor, Object> entry :
+        getAllFields().entrySet()) {
+      final FieldDescriptor field = entry.getKey();
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         if (field.isRepeated()) {
-          for (Message element : (List<Message>) entry.getValue()) {
+          for (final Message element : (List<Message>) entry.getValue()) {
             if (!element.isInitialized()) {
               return false;
             }
@@ -83,117 +85,59 @@
     return TextFormat.printToString(this);
   }
 
-  public void writeTo(CodedOutputStream output) throws IOException {
-    for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      if (field.isRepeated()) {
-        List valueList = (List) entry.getValue();
-        if (field.getOptions().getPacked()) {
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    final boolean isMessageSet =
+        getDescriptorForType().getOptions().getMessageSetWireFormat();
 
-          output.writeTag(field.getNumber(),
-                          WireFormat.WIRETYPE_LENGTH_DELIMITED);
-          int dataSize = 0;
-          for (Object element : valueList) {
-            dataSize += CodedOutputStream.computeFieldSizeNoTag(
-                field.getType(), element);
-          }
-          output.writeRawVarint32(dataSize);
-
-          for (Object element : valueList) {
-            output.writeFieldNoTag(field.getType(), element);
-          }
-        } else {
-          for (Object element : valueList) {
-            output.writeField(field.getType(), field.getNumber(), element);
-          }
-        }
+    for (final Map.Entry<FieldDescriptor, Object> entry :
+        getAllFields().entrySet()) {
+      final FieldDescriptor field = entry.getKey();
+      final Object value = entry.getValue();
+      if (isMessageSet && field.isExtension() &&
+          field.getType() == FieldDescriptor.Type.MESSAGE &&
+          !field.isRepeated()) {
+        output.writeMessageSetExtension(field.getNumber(), (Message) value);
       } else {
-        output.writeField(field.getType(), field.getNumber(), entry.getValue());
+        FieldSet.writeField(field, value, output);
       }
     }
 
-    UnknownFieldSet unknownFields = getUnknownFields();
-    if (getDescriptorForType().getOptions().getMessageSetWireFormat()) {
+    final UnknownFieldSet unknownFields = getUnknownFields();
+    if (isMessageSet) {
       unknownFields.writeAsMessageSetTo(output);
     } else {
       unknownFields.writeTo(output);
     }
   }
 
-  public ByteString toByteString() {
-    try {
-      ByteString.CodedBuilder out =
-        ByteString.newCodedBuilder(getSerializedSize());
-      writeTo(out.getCodedOutput());
-      return out.build();
-    } catch (IOException e) {
-      throw new RuntimeException(
-        "Serializing to a ByteString threw an IOException (should " +
-        "never happen).", e);
-    }
-  }
-
-  public byte[] toByteArray() {
-    try {
-      byte[] result = new byte[getSerializedSize()];
-      CodedOutputStream output = CodedOutputStream.newInstance(result);
-      writeTo(output);
-      output.checkNoSpaceLeft();
-      return result;
-    } catch (IOException e) {
-      throw new RuntimeException(
-        "Serializing to a byte array threw an IOException " +
-        "(should never happen).", e);
-    }
-  }
-
-  public void writeTo(OutputStream output) throws IOException {
-    CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
-    writeTo(codedOutput);
-    codedOutput.flush();
-  }
-
-  public void writeDelimitedTo(OutputStream output) throws IOException {
-    CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
-    codedOutput.writeRawVarint32(getSerializedSize());
-    writeTo(codedOutput);
-    codedOutput.flush();
-  }
-
   private int memoizedSize = -1;
 
   public int getSerializedSize() {
     int size = memoizedSize;
-    if (size != -1) return size;
+    if (size != -1) {
+      return size;
+    }
 
     size = 0;
-    for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      if (field.isRepeated()) {
-        List valueList = (List) entry.getValue();
-        if (field.getOptions().getPacked()) {
-          int dataSize = 0;
-          for (Object element : valueList) {
-            dataSize += CodedOutputStream.computeFieldSizeNoTag(
-                field.getType(), element);
-          }
-          size += dataSize;
-          size += CodedOutputStream.computeTagSize(field.getNumber());
-          size += CodedOutputStream.computeRawVarint32Size(dataSize);
-        } else {
-          for (Object element : valueList) {
-            size += CodedOutputStream.computeFieldSize(
-                field.getType(), field.getNumber(), element);
-          }
-        }
+    final boolean isMessageSet =
+        getDescriptorForType().getOptions().getMessageSetWireFormat();
+
+    for (final Map.Entry<FieldDescriptor, Object> entry :
+        getAllFields().entrySet()) {
+      final FieldDescriptor field = entry.getKey();
+      final Object value = entry.getValue();
+      if (isMessageSet && field.isExtension() &&
+          field.getType() == FieldDescriptor.Type.MESSAGE &&
+          !field.isRepeated()) {
+        size += CodedOutputStream.computeMessageSetExtensionSize(
+            field.getNumber(), (Message) value);
       } else {
-        size += CodedOutputStream.computeFieldSize(
-          field.getType(), field.getNumber(), entry.getValue());
+        size += FieldSet.computeFieldSize(field, value);
       }
     }
 
-    UnknownFieldSet unknownFields = getUnknownFields();
-    if (getDescriptorForType().getOptions().getMessageSetWireFormat()) {
+    final UnknownFieldSet unknownFields = getUnknownFields();
+    if (isMessageSet) {
       size += unknownFields.getSerializedSizeAsMessageSet();
     } else {
       size += unknownFields.getSerializedSize();
@@ -204,14 +148,14 @@
   }
 
   @Override
-  public boolean equals(Object other) {
+  public boolean equals(final Object other) {
     if (other == this) {
       return true;
     }
     if (!(other instanceof Message)) {
       return false;
     }
-    Message otherMessage = (Message) other;
+    final Message otherMessage = (Message) other;
     if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
       return false;
     }
@@ -237,20 +181,21 @@
    */
   @SuppressWarnings("unchecked")
   public static abstract class Builder<BuilderType extends Builder>
+      extends AbstractMessageLite.Builder<BuilderType>
       implements Message.Builder {
     // The compiler produces an error if this is not declared explicitly.
     @Override
     public abstract BuilderType clone();
 
     public BuilderType clear() {
-      for (Map.Entry<FieldDescriptor, Object> entry :
+      for (final Map.Entry<FieldDescriptor, Object> entry :
            getAllFields().entrySet()) {
         clearField(entry.getKey());
       }
       return (BuilderType) this;
     }
 
-    public BuilderType mergeFrom(Message other) {
+    public BuilderType mergeFrom(final Message other) {
       if (other.getDescriptorForType() != getDescriptorForType()) {
         throw new IllegalArgumentException(
           "mergeFrom(Message) can only merge messages of the same type.");
@@ -265,15 +210,15 @@
       // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
       //   which allows people to make secure deep copies of messages.
 
-      for (Map.Entry<FieldDescriptor, Object> entry :
+      for (final Map.Entry<FieldDescriptor, Object> entry :
            other.getAllFields().entrySet()) {
-        FieldDescriptor field = entry.getKey();
+        final FieldDescriptor field = entry.getKey();
         if (field.isRepeated()) {
-          for (Object element : (List)entry.getValue()) {
+          for (final Object element : (List)entry.getValue()) {
             addRepeatedField(field, element);
           }
         } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-          Message existingValue = (Message)getField(field);
+          final Message existingValue = (Message)getField(field);
           if (existingValue == existingValue.getDefaultInstanceForType()) {
             setField(field, entry.getValue());
           } else {
@@ -288,24 +233,288 @@
         }
       }
 
+      mergeUnknownFields(other.getUnknownFields());
+
       return (BuilderType) this;
     }
 
-    public BuilderType mergeFrom(CodedInputStream input) throws IOException {
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input)
+                                 throws IOException {
       return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
     }
 
-    public BuilderType mergeFrom(CodedInputStream input,
-                                 ExtensionRegistry extensionRegistry)
-                                 throws IOException {
-      UnknownFieldSet.Builder unknownFields =
+    @Override
+    public BuilderType mergeFrom(
+        final CodedInputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      final UnknownFieldSet.Builder unknownFields =
         UnknownFieldSet.newBuilder(getUnknownFields());
-      FieldSet.mergeFrom(input, unknownFields, extensionRegistry, this);
+      while (true) {
+        final int tag = input.readTag();
+        if (tag == 0) {
+          break;
+        }
+
+        if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
+                            this, tag)) {
+          // end group tag
+          break;
+        }
+      }
       setUnknownFields(unknownFields.build());
       return (BuilderType) this;
     }
 
-    public BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) {
+    /**
+     * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
+     * ExtensionRegistryLite, Message.Builder)}, but parses a single field.
+     * Package-private because it is used by GeneratedMessage.ExtendableMessage.
+     * @param tag The tag, which should have already been read.
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    @SuppressWarnings("unchecked")
+    static boolean mergeFieldFrom(
+        final CodedInputStream input,
+        final UnknownFieldSet.Builder unknownFields,
+        final ExtensionRegistryLite extensionRegistry,
+        final Message.Builder builder,
+        final int tag) throws IOException {
+      final Descriptor type = builder.getDescriptorForType();
+
+      if (type.getOptions().getMessageSetWireFormat() &&
+          tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
+        mergeMessageSetExtensionFromCodedStream(
+          input, unknownFields, extensionRegistry, builder);
+        return true;
+      }
+
+      final int wireType = WireFormat.getTagWireType(tag);
+      final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+      final FieldDescriptor field;
+      Message defaultInstance = null;
+
+      if (type.isExtensionNumber(fieldNumber)) {
+        // extensionRegistry may be either ExtensionRegistry or
+        // ExtensionRegistryLite.  Since the type we are parsing is a full
+        // message, only a full ExtensionRegistry could possibly contain
+        // extensions of it.  Otherwise we will treat the registry as if it
+        // were empty.
+        if (extensionRegistry instanceof ExtensionRegistry) {
+          final ExtensionRegistry.ExtensionInfo extension =
+            ((ExtensionRegistry) extensionRegistry)
+              .findExtensionByNumber(type, fieldNumber);
+          if (extension == null) {
+            field = null;
+          } else {
+            field = extension.descriptor;
+            defaultInstance = extension.defaultInstance;
+          }
+        } else {
+          field = null;
+        }
+      } else {
+        field = type.findFieldByNumber(fieldNumber);
+      }
+
+      if (field == null || wireType !=
+            FieldSet.getWireFormatForFieldType(
+                field.getLiteType(),
+                field.getOptions().getPacked())) {
+        // Unknown field or wrong wire type.  Skip.
+        return unknownFields.mergeFieldFrom(tag, input);
+      }
+
+      if (field.getOptions().getPacked()) {
+        final int length = input.readRawVarint32();
+        final int limit = input.pushLimit(length);
+        if (field.getLiteType() == WireFormat.FieldType.ENUM) {
+          while (input.getBytesUntilLimit() > 0) {
+            final int rawValue = input.readEnum();
+            final Object value = field.getEnumType().findValueByNumber(rawValue);
+            if (value == null) {
+              // If the number isn't recognized as a valid value for this
+              // enum, drop it (don't even add it to unknownFields).
+              return true;
+            }
+            builder.addRepeatedField(field, value);
+          }
+        } else {
+          while (input.getBytesUntilLimit() > 0) {
+            final Object value =
+              FieldSet.readPrimitiveField(input, field.getLiteType());
+            builder.addRepeatedField(field, value);
+          }
+        }
+        input.popLimit(limit);
+      } else {
+        final Object value;
+        switch (field.getType()) {
+          case GROUP: {
+            final Message.Builder subBuilder;
+            if (defaultInstance != null) {
+              subBuilder = defaultInstance.newBuilderForType();
+            } else {
+              subBuilder = builder.newBuilderForField(field);
+            }
+            if (!field.isRepeated()) {
+              subBuilder.mergeFrom((Message) builder.getField(field));
+            }
+            input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
+            value = subBuilder.build();
+            break;
+          }
+          case MESSAGE: {
+            final Message.Builder subBuilder;
+            if (defaultInstance != null) {
+              subBuilder = defaultInstance.newBuilderForType();
+            } else {
+              subBuilder = builder.newBuilderForField(field);
+            }
+            if (!field.isRepeated()) {
+              subBuilder.mergeFrom((Message) builder.getField(field));
+            }
+            input.readMessage(subBuilder, extensionRegistry);
+            value = subBuilder.build();
+            break;
+          }
+          case ENUM:
+            final int rawValue = input.readEnum();
+            value = field.getEnumType().findValueByNumber(rawValue);
+            // If the number isn't recognized as a valid value for this enum,
+            // drop it.
+            if (value == null) {
+              unknownFields.mergeVarintField(fieldNumber, rawValue);
+              return true;
+            }
+            break;
+          default:
+            value = FieldSet.readPrimitiveField(input, field.getLiteType());
+            break;
+        }
+
+        if (field.isRepeated()) {
+          builder.addRepeatedField(field, value);
+        } else {
+          builder.setField(field, value);
+        }
+      }
+
+      return true;
+    }
+
+    /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
+    private static void mergeMessageSetExtensionFromCodedStream(
+        final CodedInputStream input,
+        final UnknownFieldSet.Builder unknownFields,
+        final ExtensionRegistryLite extensionRegistry,
+        final Message.Builder builder) throws IOException {
+      final Descriptor type = builder.getDescriptorForType();
+
+      // The wire format for MessageSet is:
+      //   message MessageSet {
+      //     repeated group Item = 1 {
+      //       required int32 typeId = 2;
+      //       required bytes message = 3;
+      //     }
+      //   }
+      // "typeId" is the extension's field number.  The extension can only be
+      // a message type, where "message" contains the encoded bytes of that
+      // message.
+      //
+      // In practice, we will probably never see a MessageSet item in which
+      // the message appears before the type ID, or where either field does not
+      // appear exactly once.  However, in theory such cases are valid, so we
+      // should be prepared to accept them.
+
+      int typeId = 0;
+      ByteString rawBytes = null;  // If we encounter "message" before "typeId"
+      Message.Builder subBuilder = null;
+      FieldDescriptor field = null;
+
+      while (true) {
+        final int tag = input.readTag();
+        if (tag == 0) {
+          break;
+        }
+
+        if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
+          typeId = input.readUInt32();
+          // Zero is not a valid type ID.
+          if (typeId != 0) {
+            final ExtensionRegistry.ExtensionInfo extension;
+
+            // extensionRegistry may be either ExtensionRegistry or
+            // ExtensionRegistryLite.  Since the type we are parsing is a full
+            // message, only a full ExtensionRegistry could possibly contain
+            // extensions of it.  Otherwise we will treat the registry as if it
+            // were empty.
+            if (extensionRegistry instanceof ExtensionRegistry) {
+              extension = ((ExtensionRegistry) extensionRegistry)
+                  .findExtensionByNumber(type, typeId);
+            } else {
+              extension = null;
+            }
+
+            if (extension != null) {
+              field = extension.descriptor;
+              subBuilder = extension.defaultInstance.newBuilderForType();
+              final Message originalMessage = (Message)builder.getField(field);
+              if (originalMessage != null) {
+                subBuilder.mergeFrom(originalMessage);
+              }
+              if (rawBytes != null) {
+                // We already encountered the message.  Parse it now.
+                subBuilder.mergeFrom(
+                  CodedInputStream.newInstance(rawBytes.newInput()));
+                rawBytes = null;
+              }
+            } else {
+              // Unknown extension number.  If we already saw data, put it
+              // in rawBytes.
+              if (rawBytes != null) {
+                unknownFields.mergeField(typeId,
+                  UnknownFieldSet.Field.newBuilder()
+                    .addLengthDelimited(rawBytes)
+                    .build());
+                rawBytes = null;
+              }
+            }
+          }
+        } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+          if (typeId == 0) {
+            // We haven't seen a type ID yet, so we have to store the raw bytes
+            // for now.
+            rawBytes = input.readBytes();
+          } else if (subBuilder == null) {
+            // We don't know how to parse this.  Ignore it.
+            unknownFields.mergeField(typeId,
+              UnknownFieldSet.Field.newBuilder()
+                .addLengthDelimited(input.readBytes())
+                .build());
+          } else {
+            // We already know the type, so we can parse directly from the input
+            // with no copying.  Hooray!
+            input.readMessage(subBuilder, extensionRegistry);
+          }
+        } else {
+          // Unknown tag.  Skip it.
+          if (!input.skipField(tag)) {
+            break;  // end of group
+          }
+        }
+      }
+
+      input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
+
+      if (subBuilder != null) {
+        builder.setField(field, subBuilder.build());
+      }
+    }
+
+    public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
       setUnknownFields(
         UnknownFieldSet.newBuilder(getUnknownFields())
                        .mergeFrom(unknownFields)
@@ -313,145 +522,169 @@
       return (BuilderType) this;
     }
 
-    public BuilderType mergeFrom(ByteString data)
-        throws InvalidProtocolBufferException {
-      try {
-        CodedInputStream input = data.newCodedInput();
-        mergeFrom(input);
-        input.checkLastTagWas(0);
-        return (BuilderType) this;
-      } catch (InvalidProtocolBufferException e) {
-        throw e;
-      } catch (IOException e) {
-        throw new RuntimeException(
-          "Reading from a ByteString threw an IOException (should " +
-          "never happen).", e);
+    /**
+     * Construct an UninitializedMessageException reporting missing fields in
+     * the given message.
+     */
+    protected static UninitializedMessageException
+        newUninitializedMessageException(Message message) {
+      return new UninitializedMessageException(findMissingFields(message));
+    }
+
+    /**
+     * Populates {@code this.missingFields} with the full "path" of each
+     * missing required field in the given message.
+     */
+    private static List<String> findMissingFields(final Message message) {
+      final List<String> results = new ArrayList<String>();
+      findMissingFields(message, "", results);
+      return results;
+    }
+
+    /** Recursive helper implementing {@link #findMissingFields(Message)}. */
+    private static void findMissingFields(final Message message,
+                                          final String prefix,
+                                          final List<String> results) {
+      for (final FieldDescriptor field :
+          message.getDescriptorForType().getFields()) {
+        if (field.isRequired() && !message.hasField(field)) {
+          results.add(prefix + field.getName());
+        }
+      }
+
+      for (final Map.Entry<FieldDescriptor, Object> entry :
+           message.getAllFields().entrySet()) {
+        final FieldDescriptor field = entry.getKey();
+        final Object value = entry.getValue();
+
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          if (field.isRepeated()) {
+            int i = 0;
+            for (final Object element : (List) value) {
+              findMissingFields((Message) element,
+                                subMessagePrefix(prefix, field, i++),
+                                results);
+            }
+          } else {
+            if (message.hasField(field)) {
+              findMissingFields((Message) value,
+                                subMessagePrefix(prefix, field, -1),
+                                results);
+            }
+          }
+        }
       }
     }
 
-    public BuilderType mergeFrom(ByteString data,
-                                 ExtensionRegistry extensionRegistry)
-                                 throws InvalidProtocolBufferException {
-      try {
-        CodedInputStream input = data.newCodedInput();
-        mergeFrom(input, extensionRegistry);
-        input.checkLastTagWas(0);
-        return (BuilderType) this;
-      } catch (InvalidProtocolBufferException e) {
-        throw e;
-      } catch (IOException e) {
-        throw new RuntimeException(
-          "Reading from a ByteString threw an IOException (should " +
-          "never happen).", e);
+    private static String subMessagePrefix(final String prefix,
+                                           final FieldDescriptor field,
+                                           final int index) {
+      final StringBuilder result = new StringBuilder(prefix);
+      if (field.isExtension()) {
+        result.append('(')
+              .append(field.getFullName())
+              .append(')');
+      } else {
+        result.append(field.getName());
       }
-    }
-
-    public BuilderType mergeFrom(byte[] data)
-        throws InvalidProtocolBufferException {
-      return mergeFrom(data, 0, data.length);
-    }
-
-    public BuilderType mergeFrom(byte[] data, int off, int len)
-        throws InvalidProtocolBufferException {
-      try {
-        CodedInputStream input = CodedInputStream.newInstance(data, off, len);
-        mergeFrom(input);
-        input.checkLastTagWas(0);
-        return (BuilderType) this;
-      } catch (InvalidProtocolBufferException e) {
-        throw e;
-      } catch (IOException e) {
-        throw new RuntimeException(
-          "Reading from a byte array threw an IOException (should " +
-          "never happen).", e);
+      if (index != -1) {
+        result.append('[')
+              .append(index)
+              .append(']');
       }
+      result.append('.');
+      return result.toString();
     }
 
+    // ===============================================================
+    // The following definitions seem to be required in order to make javac
+    // not produce weird errors like:
+    //
+    // java/com/google/protobuf/DynamicMessage.java:203: types
+    //   com.google.protobuf.AbstractMessage.Builder<
+    //     com.google.protobuf.DynamicMessage.Builder> and
+    //   com.google.protobuf.AbstractMessage.Builder<
+    //     com.google.protobuf.DynamicMessage.Builder> are incompatible; both
+    //   define mergeFrom(com.google.protobuf.ByteString), but with unrelated
+    //   return types.
+    //
+    // Strangely, these lines are only needed if javac is invoked separately
+    // on AbstractMessage.java and AbstractMessageLite.java.  If javac is
+    // invoked on both simultaneously, it works.  (Or maybe the important
+    // point is whether or not DynamicMessage.java is compiled together with
+    // AbstractMessageLite.java -- not sure.)  I suspect this is a compiler
+    // bug.
+
+    @Override
+    public BuilderType mergeFrom(final ByteString data)
+        throws InvalidProtocolBufferException {
+      return super.mergeFrom(data);
+    }
+
+    @Override
     public BuilderType mergeFrom(
-        byte[] data,
-        ExtensionRegistry extensionRegistry)
+        final ByteString data,
+        final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
-      return mergeFrom(data, 0, data.length, extensionRegistry);
+      return super.mergeFrom(data, extensionRegistry);
     }
 
+    @Override
+    public BuilderType mergeFrom(final byte[] data)
+        throws InvalidProtocolBufferException {
+      return super.mergeFrom(data);
+    }
+
+    @Override
     public BuilderType mergeFrom(
-        byte[] data, int off, int len,
-        ExtensionRegistry extensionRegistry)
+        final byte[] data, final int off, final int len)
         throws InvalidProtocolBufferException {
-      try {
-        CodedInputStream input = CodedInputStream.newInstance(data, off, len);
-        mergeFrom(input, extensionRegistry);
-        input.checkLastTagWas(0);
-        return (BuilderType) this;
-      } catch (InvalidProtocolBufferException e) {
-        throw e;
-      } catch (IOException e) {
-        throw new RuntimeException(
-          "Reading from a byte array threw an IOException (should " +
-          "never happen).", e);
-      }
+      return super.mergeFrom(data, off, len);
     }
 
-    public BuilderType mergeFrom(InputStream input) throws IOException {
-      CodedInputStream codedInput = CodedInputStream.newInstance(input);
-      mergeFrom(codedInput);
-      codedInput.checkLastTagWas(0);
-      return (BuilderType) this;
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return super.mergeFrom(data, extensionRegistry);
     }
 
-    public BuilderType mergeFrom(InputStream input,
-                                 ExtensionRegistry extensionRegistry)
-                                 throws IOException {
-      CodedInputStream codedInput = CodedInputStream.newInstance(input);
-      mergeFrom(codedInput, extensionRegistry);
-      codedInput.checkLastTagWas(0);
-      return (BuilderType) this;
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data, final int off, final int len,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return super.mergeFrom(data, off, len, extensionRegistry);
     }
 
-    public BuilderType mergeDelimitedFrom(InputStream input,
-                                          ExtensionRegistry extensionRegistry)
-                                          throws IOException {
-      final int size = CodedInputStream.readRawVarint32(input);
-
-      // A stream which will not read more than |size| bytes.
-      InputStream limitedInput = new FilterInputStream(input) {
-        int limit = size;
-
-        @Override
-        public int available() throws IOException {
-          return Math.min(super.available(), limit);
-        }
-
-        @Override
-        public int read() throws IOException {
-          if (limit <= 0) return -1;
-          int result = super.read();
-          if (result >= 0) --limit;
-          return result;
-        }
-
-        @Override
-        public int read(byte[] b, int off, int len) throws IOException {
-          if (limit <= 0) return -1;
-          len = Math.min(len, limit);
-          int result = super.read(b, off, len);
-          if (result >= 0) limit -= result;
-          return result;
-        }
-
-        @Override
-        public long skip(long n) throws IOException {
-          long result = super.skip(Math.min(n, limit));
-          if (result >= 0) limit -= result;
-          return result;
-        }
-      };
-      return mergeFrom(limitedInput, extensionRegistry);
-    }
-
-    public BuilderType mergeDelimitedFrom(InputStream input)
+    @Override
+    public BuilderType mergeFrom(final InputStream input)
         throws IOException {
-      return mergeDelimitedFrom(input, ExtensionRegistry.getEmptyRegistry());
+      return super.mergeFrom(input);
     }
+
+    @Override
+    public BuilderType mergeFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return super.mergeFrom(input, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeDelimitedFrom(final InputStream input)
+        throws IOException {
+      return super.mergeDelimitedFrom(input);
+    }
+
+    @Override
+    public BuilderType mergeDelimitedFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return super.mergeDelimitedFrom(input, extensionRegistry);
+    }
+
   }
 }
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
new file mode 100644
index 0000000..489577d
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -0,0 +1,321 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * A partial implementation of the {@link MessageLite} interface which
+ * implements as many methods of that interface as possible in terms of other
+ * methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessageLite implements MessageLite {
+  public ByteString toByteString() {
+    try {
+      final ByteString.CodedBuilder out =
+        ByteString.newCodedBuilder(getSerializedSize());
+      writeTo(out.getCodedOutput());
+      return out.build();
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Serializing to a ByteString threw an IOException (should " +
+        "never happen).", e);
+    }
+  }
+
+  public byte[] toByteArray() {
+    try {
+      final byte[] result = new byte[getSerializedSize()];
+      final CodedOutputStream output = CodedOutputStream.newInstance(result);
+      writeTo(output);
+      output.checkNoSpaceLeft();
+      return result;
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Serializing to a byte array threw an IOException " +
+        "(should never happen).", e);
+    }
+  }
+
+  public void writeTo(final OutputStream output) throws IOException {
+    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  public void writeDelimitedTo(final OutputStream output) throws IOException {
+    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+    codedOutput.writeRawVarint32(getSerializedSize());
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  /**
+   * A partial implementation of the {@link Message.Builder} interface which
+   * implements as many methods of that interface as possible in terms of
+   * other methods.
+   */
+  @SuppressWarnings("unchecked")
+  public static abstract class Builder<BuilderType extends Builder>
+      implements MessageLite.Builder {
+    // The compiler produces an error if this is not declared explicitly.
+    @Override
+    public abstract BuilderType clone();
+
+    public BuilderType mergeFrom(final CodedInputStream input)
+                                 throws IOException {
+      // TODO(kenton):  Don't use null here.  Currently we have to because
+      //   using ExtensionRegistry.getEmptyRegistry() would imply a dependency
+      //   on ExtensionRegistry.  However, AbstractMessage overrides this with
+      //   a correct implementation, and lite messages don't yet support
+      //   extensions, so it ends up not mattering for now.  It will matter
+      //   once lite messages support extensions.
+      return mergeFrom(input, null);
+    }
+
+    // Re-defined here for return type covariance.
+    public abstract BuilderType mergeFrom(
+        final CodedInputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+
+    public BuilderType mergeFrom(final ByteString data)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    public BuilderType mergeFrom(
+        final ByteString data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input, extensionRegistry);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    public BuilderType mergeFrom(final byte[] data)
+        throws InvalidProtocolBufferException {
+      return mergeFrom(data, 0, data.length);
+    }
+
+    public BuilderType mergeFrom(final byte[] data, final int off,
+                                 final int len)
+                                 throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    public BuilderType mergeFrom(
+        final byte[] data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return mergeFrom(data, 0, data.length, extensionRegistry);
+    }
+
+    public BuilderType mergeFrom(
+        final byte[] data, final int off, final int len,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input, extensionRegistry);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    public BuilderType mergeFrom(final InputStream input) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput);
+      codedInput.checkLastTagWas(0);
+      return (BuilderType) this;
+    }
+
+    public BuilderType mergeFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput, extensionRegistry);
+      codedInput.checkLastTagWas(0);
+      return (BuilderType) this;
+    }
+
+    /**
+     * An InputStream implementations which reads from some other InputStream
+     * but is limited to a particular number of bytes.  Used by
+     * mergeDelimitedFrom().  This is intentionally package-private so that
+     * UnknownFieldSet can share it.
+     */
+    static final class LimitedInputStream extends FilterInputStream {
+      private int limit;
+
+      LimitedInputStream(InputStream in, int limit) {
+        super(in);
+        this.limit = limit;
+      }
+
+      @Override
+      public int available() throws IOException {
+        return Math.min(super.available(), limit);
+      }
+
+      @Override
+      public int read() throws IOException {
+        if (limit <= 0) {
+          return -1;
+        }
+        final int result = super.read();
+        if (result >= 0) {
+          --limit;
+        }
+        return result;
+      }
+
+      @Override
+      public int read(final byte[] b, final int off, int len)
+                      throws IOException {
+        if (limit <= 0) {
+          return -1;
+        }
+        len = Math.min(len, limit);
+        final int result = super.read(b, off, len);
+        if (result >= 0) {
+          limit -= result;
+        }
+        return result;
+      }
+
+      @Override
+      public long skip(final long n) throws IOException {
+        final long result = super.skip(Math.min(n, limit));
+        if (result >= 0) {
+          limit -= result;
+        }
+        return result;
+      }
+    }
+
+    public BuilderType mergeDelimitedFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      final int size = CodedInputStream.readRawVarint32(input);
+      final InputStream limitedInput = new LimitedInputStream(input, size);
+      return mergeFrom(limitedInput, extensionRegistry);
+    }
+
+    public BuilderType mergeDelimitedFrom(final InputStream input)
+        throws IOException {
+      final int size = CodedInputStream.readRawVarint32(input);
+      final InputStream limitedInput = new LimitedInputStream(input, size);
+      return mergeFrom(limitedInput);
+    }
+
+    /**
+     * Construct an UninitializedMessageException reporting missing fields in
+     * the given message.
+     */
+    protected static UninitializedMessageException
+        newUninitializedMessageException(MessageLite message) {
+      return new UninitializedMessageException(message);
+    }
+
+    /**
+     * Adds the {@code values} to the {@code list}.  This is a helper method
+     * used by generated code.  Users should ignore it.
+     *
+     * @throws NullPointerException if any of the elements of {@code values} is
+     * null.
+     */
+    protected static <T> void addAll(final Iterable<T> values,
+                                     final Collection<? super T> list) {
+      for (final T value : values) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+      }
+      if (values instanceof Collection) {
+        @SuppressWarnings("unsafe") final
+        Collection<T> collection = (Collection<T>) values;
+        list.addAll(collection);
+      } else {
+        for (final T value : values) {
+          list.add(value);
+        }
+      }
+    }
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index f376e7a..c83c335 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -46,7 +46,7 @@
 public final class ByteString {
   private final byte[] bytes;
 
-  private ByteString(byte[] bytes) {
+  private ByteString(final byte[] bytes) {
     this.bytes = bytes;
   }
 
@@ -55,7 +55,7 @@
    *
    * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
    */
-  public byte byteAt(int index) {
+  public byte byteAt(final int index) {
     return bytes[index];
   }
 
@@ -63,14 +63,14 @@
    * Gets the number of bytes.
    */
   public int size() {
-    return this.bytes.length;
+    return bytes.length;
   }
 
   /**
    * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
    */
   public boolean isEmpty() {
-    return this.bytes.length == 0;
+    return bytes.length == 0;
   }
 
   // =================================================================
@@ -84,8 +84,9 @@
   /**
    * Copies the given bytes into a {@code ByteString}.
    */
-  public static ByteString copyFrom(byte[] bytes, int offset, int size) {
-    byte[] copy = new byte[size];
+  public static ByteString copyFrom(final byte[] bytes, final int offset,
+                                    final int size) {
+    final byte[] copy = new byte[size];
     System.arraycopy(bytes, offset, copy, 0, size);
     return new ByteString(copy);
   }
@@ -93,7 +94,7 @@
   /**
    * Copies the given bytes into a {@code ByteString}.
    */
-  public static ByteString copyFrom(byte[] bytes) {
+  public static ByteString copyFrom(final byte[] bytes) {
     return copyFrom(bytes, 0, bytes.length);
   }
 
@@ -101,7 +102,7 @@
    * Encodes {@code text} into a sequence of bytes using the named charset
    * and returns the result as a {@code ByteString}.
    */
-  public static ByteString copyFrom(String text, String charsetName)
+  public static ByteString copyFrom(final String text, final String charsetName)
       throws UnsupportedEncodingException {
     return new ByteString(text.getBytes(charsetName));
   }
@@ -110,7 +111,7 @@
    * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
    * result as a {@code ByteString}.
    */
-  public static ByteString copyFromUtf8(String text) {
+  public static ByteString copyFromUtf8(final String text) {
     try {
       return new ByteString(text.getBytes("UTF-8"));
     } catch (UnsupportedEncodingException e) {
@@ -127,7 +128,7 @@
    * @param target buffer to copy into
    * @param offset in the target buffer
    */
-  public void copyTo(byte[] target, int offset) {
+  public void copyTo(final byte[] target, final int offset) {
     System.arraycopy(bytes, 0, target, offset, bytes.length);
   }
 
@@ -139,8 +140,9 @@
    * @param targetOffset offset within the target buffer
    * @param size number of bytes to copy
    */
-  public void copyTo(byte[] target, int sourceOffset, int targetOffset,
-      int size) {
+  public void copyTo(final byte[] target, final int sourceOffset,
+                     final int targetOffset,
+      final int size) {
     System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
   }
 
@@ -148,9 +150,9 @@
    * Copies bytes to a {@code byte[]}.
    */
   public byte[] toByteArray() {
-    int size = this.bytes.length;
-    byte[] copy = new byte[size];
-    System.arraycopy(this.bytes, 0, copy, 0, size);
+    final int size = bytes.length;
+    final byte[] copy = new byte[size];
+    System.arraycopy(bytes, 0, copy, 0, size);
     return copy;
   }
 
@@ -159,7 +161,7 @@
    * same backing byte array.
    */
   public ByteBuffer asReadOnlyByteBuffer() {
-    ByteBuffer byteBuffer = ByteBuffer.wrap(this.bytes);
+    final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
     return byteBuffer.asReadOnlyBuffer();
   }
 
@@ -167,9 +169,9 @@
    * Constructs a new {@code String} by decoding the bytes using the
    * specified charset.
    */
-  public String toString(String charsetName)
+  public String toString(final String charsetName)
       throws UnsupportedEncodingException {
-    return new String(this.bytes, charsetName);
+    return new String(bytes, charsetName);
   }
 
   /**
@@ -177,7 +179,7 @@
    */
   public String toStringUtf8() {
     try {
-      return new String(this.bytes, "UTF-8");
+      return new String(bytes, "UTF-8");
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported?", e);
     }
@@ -187,7 +189,7 @@
   // equals() and hashCode()
 
   @Override
-  public boolean equals(Object o) {
+  public boolean equals(final Object o) {
     if (o == this) {
       return true;
     }
@@ -196,16 +198,16 @@
       return false;
     }
 
-    ByteString other = (ByteString) o;
-    int size = this.bytes.length;
+    final ByteString other = (ByteString) o;
+    final int size = bytes.length;
     if (size != other.bytes.length) {
       return false;
     }
 
-    byte[] bytes = this.bytes;
-    byte[] otherBytes = other.bytes;
+    final byte[] thisBytes = bytes;
+    final byte[] otherBytes = other.bytes;
     for (int i = 0; i < size; i++) {
-      if (bytes[i] != otherBytes[i]) {
+      if (thisBytes[i] != otherBytes[i]) {
         return false;
       }
     }
@@ -213,25 +215,25 @@
     return true;
   }
 
-  volatile int hash = 0;
+  private volatile int hash = 0;
 
   @Override
   public int hashCode() {
-    int h = this.hash;
+    int h = hash;
 
     if (h == 0) {
-      byte[] bytes = this.bytes;
-      int size = this.bytes.length;
+      final byte[] thisBytes = bytes;
+      final int size = bytes.length;
 
       h = size;
       for (int i = 0; i < size; i++) {
-        h = h * 31 + bytes[i];
+        h = h * 31 + thisBytes[i];
       }
       if (h == 0) {
         h = 1;
       }
 
-      this.hash = h;
+      hash = h;
     }
 
     return h;
@@ -264,7 +266,7 @@
   /**
    * Creates a new {@link Output} with the given initial capacity.
    */
-  public static Output newOutput(int initialCapacity) {
+  public static Output newOutput(final int initialCapacity) {
     return new Output(new ByteArrayOutputStream(initialCapacity));
   }
 
@@ -285,7 +287,7 @@
     /**
      * Constructs a new output with the given initial capacity.
      */
-    private Output(ByteArrayOutputStream bout) {
+    private Output(final ByteArrayOutputStream bout) {
       super(bout);
       this.bout = bout;
     }
@@ -294,14 +296,14 @@
      * Creates a {@code ByteString} instance from this {@code Output}.
      */
     public ByteString toByteString() {
-      byte[] byteArray = bout.toByteArray();
+      final byte[] byteArray = bout.toByteArray();
       return new ByteString(byteArray);
     }
   }
 
   /**
    * Constructs a new ByteString builder, which allows you to efficiently
-   * construct a {@code ByteString} by writing to a {@link CodedOutputSteam}.
+   * construct a {@code ByteString} by writing to a {@link CodedOutputStream}.
    * Using this is much more efficient than calling {@code newOutput()} and
    * wrapping that in a {@code CodedOutputStream}.
    *
@@ -312,7 +314,7 @@
    * @param size The target byte size of the {@code ByteString}.  You must
    *             write exactly this many bytes before building the result.
    */
-  static CodedBuilder newCodedBuilder(int size) {
+  static CodedBuilder newCodedBuilder(final int size) {
     return new CodedBuilder(size);
   }
 
@@ -321,7 +323,7 @@
     private final CodedOutputStream output;
     private final byte[] buffer;
 
-    private CodedBuilder(int size) {
+    private CodedBuilder(final int size) {
       buffer = new byte[size];
       output = CodedOutputStream.newInstance(buffer);
     }
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index b6be2e8..9125957 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -51,21 +51,22 @@
   /**
    * Create a new CodedInputStream wrapping the given InputStream.
    */
-  public static CodedInputStream newInstance(InputStream input) {
+  public static CodedInputStream newInstance(final InputStream input) {
     return new CodedInputStream(input);
   }
 
   /**
    * Create a new CodedInputStream wrapping the given byte array.
    */
-  public static CodedInputStream newInstance(byte[] buf) {
+  public static CodedInputStream newInstance(final byte[] buf) {
     return newInstance(buf, 0, buf.length);
   }
 
   /**
    * Create a new CodedInputStream wrapping the given byte array slice.
    */
-  public static CodedInputStream newInstance(byte[] buf, int off, int len) {
+  public static CodedInputStream newInstance(final byte[] buf, final int off,
+                                             final int len) {
     return new CodedInputStream(buf, off, len);
   }
 
@@ -98,7 +99,8 @@
    * @throws InvalidProtocolBufferException {@code value} does not match the
    *                                        last tag.
    */
-  public void checkLastTagWas(int value) throws InvalidProtocolBufferException {
+  public void checkLastTagWas(final int value)
+                              throws InvalidProtocolBufferException {
     if (lastTag != value) {
       throw InvalidProtocolBufferException.invalidEndTag();
     }
@@ -110,7 +112,7 @@
    * @return {@code false} if the tag is an endgroup tag, in which case
    *         nothing is skipped.  Otherwise, returns {@code true}.
    */
-  public boolean skipField(int tag) throws IOException {
+  public boolean skipField(final int tag) throws IOException {
     switch (WireFormat.getTagWireType(tag)) {
       case WireFormat.WIRETYPE_VARINT:
         readInt32();
@@ -143,8 +145,10 @@
    */
   public void skipMessage() throws IOException {
     while (true) {
-      int tag = readTag();
-      if (tag == 0 || !skipField(tag)) return;
+      final int tag = readTag();
+      if (tag == 0 || !skipField(tag)) {
+        return;
+      }
     }
   }
 
@@ -192,11 +196,11 @@
 
   /** Read a {@code string} field value from the stream. */
   public String readString() throws IOException {
-    int size = readRawVarint32();
+    final int size = readRawVarint32();
     if (size <= (bufferSize - bufferPos) && size > 0) {
       // Fast path:  We already have the bytes in a contiguous buffer, so
       //   just copy directly from it.
-      String result = new String(buffer, bufferPos, size, "UTF-8");
+      final String result = new String(buffer, bufferPos, size, "UTF-8");
       bufferPos += size;
       return result;
     } else {
@@ -206,8 +210,9 @@
   }
 
   /** Read a {@code group} field value from the stream. */
-  public void readGroup(int fieldNumber, Message.Builder builder,
-                        ExtensionRegistry extensionRegistry)
+  public void readGroup(final int fieldNumber,
+                        final MessageLite.Builder builder,
+                        final ExtensionRegistryLite extensionRegistry)
       throws IOException {
     if (recursionDepth >= recursionLimit) {
       throw InvalidProtocolBufferException.recursionLimitExceeded();
@@ -222,28 +227,31 @@
   /**
    * Reads a {@code group} field value from the stream and merges it into the
    * given {@link UnknownFieldSet}.
+   *
+   * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
+   *             you can just call {@link #readGroup}.
    */
-  public void readUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder)
+  @Deprecated
+  public void readUnknownGroup(final int fieldNumber,
+                               final MessageLite.Builder builder)
       throws IOException {
-    if (recursionDepth >= recursionLimit) {
-      throw InvalidProtocolBufferException.recursionLimitExceeded();
-    }
-    ++recursionDepth;
-    builder.mergeFrom(this);
-    checkLastTagWas(
-      WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
-    --recursionDepth;
+    // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
+    // is safe to pass null here.  (We can't call
+    // ExtensionRegistry.getEmptyRegistry() because that would make this
+    // class depend on ExtensionRegistry, which is not part of the lite
+    // library.)
+    readGroup(fieldNumber, builder, null);
   }
 
   /** Read an embedded message field value from the stream. */
-  public void readMessage(Message.Builder builder,
-                          ExtensionRegistry extensionRegistry)
+  public void readMessage(final MessageLite.Builder builder,
+                          final ExtensionRegistryLite extensionRegistry)
       throws IOException {
-    int length = readRawVarint32();
+    final int length = readRawVarint32();
     if (recursionDepth >= recursionLimit) {
       throw InvalidProtocolBufferException.recursionLimitExceeded();
     }
-    int oldLimit = pushLimit(length);
+    final int oldLimit = pushLimit(length);
     ++recursionDepth;
     builder.mergeFrom(this, extensionRegistry);
     checkLastTagWas(0);
@@ -253,11 +261,11 @@
 
   /** Read a {@code bytes} field value from the stream. */
   public ByteString readBytes() throws IOException {
-    int size = readRawVarint32();
-    if (size < bufferSize - bufferPos && size > 0) {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
       // Fast path:  We already have the bytes in a contiguous buffer, so
       //   just copy directly from it.
-      ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
+      final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
       bufferPos += size;
       return result;
     } else {
@@ -299,52 +307,6 @@
     return decodeZigZag64(readRawVarint64());
   }
 
-  /**
-   * Read a field of any primitive type.  Enums, groups, and embedded
-   * messages are not handled by this method.
-   *
-   * @param type Declared type of the field.
-   * @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.
-   */
-  public Object readPrimitiveField(
-      Descriptors.FieldDescriptor.Type type) throws IOException {
-    switch (type) {
-      case DOUBLE  : return readDouble  ();
-      case FLOAT   : return readFloat   ();
-      case INT64   : return readInt64   ();
-      case UINT64  : return readUInt64  ();
-      case INT32   : return readInt32   ();
-      case FIXED64 : return readFixed64 ();
-      case FIXED32 : return readFixed32 ();
-      case BOOL    : return readBool    ();
-      case STRING  : return readString  ();
-      case BYTES   : return readBytes   ();
-      case UINT32  : return readUInt32  ();
-      case SFIXED32: return readSFixed32();
-      case SFIXED64: return readSFixed64();
-      case SINT32  : return readSInt32  ();
-      case SINT64  : return 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 hanlde 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.");
-  }
-
   // =================================================================
 
   /**
@@ -373,7 +335,9 @@
           if (tmp < 0) {
             // Discard upper 32 bits.
             for (int i = 0; i < 5; i++) {
-              if (readRawByte() >= 0) return result;
+              if (readRawByte() >= 0) {
+                return result;
+              }
             }
             throw InvalidProtocolBufferException.malformedVarint();
           }
@@ -390,11 +354,11 @@
    * then you would probably end up reading past the end of the varint since
    * CodedInputStream buffers its input.
    */
-  static int readRawVarint32(InputStream input) throws IOException {
+  static int readRawVarint32(final InputStream input) throws IOException {
     int result = 0;
     int offset = 0;
     for (; offset < 32; offset += 7) {
-      int b = input.read();
+      final int b = input.read();
       if (b == -1) {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
@@ -405,7 +369,7 @@
     }
     // Keep reading up to 64 bits.
     for (; offset < 64; offset += 7) {
-      int b = input.read();
+      final int b = input.read();
       if (b == -1) {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
@@ -421,9 +385,11 @@
     int shift = 0;
     long result = 0;
     while (shift < 64) {
-      byte b = readRawByte();
+      final byte b = readRawByte();
       result |= (long)(b & 0x7F) << shift;
-      if ((b & 0x80) == 0) return result;
+      if ((b & 0x80) == 0) {
+        return result;
+      }
       shift += 7;
     }
     throw InvalidProtocolBufferException.malformedVarint();
@@ -431,10 +397,10 @@
 
   /** Read a 32-bit little-endian integer from the stream. */
   public int readRawLittleEndian32() throws IOException {
-    byte b1 = readRawByte();
-    byte b2 = readRawByte();
-    byte b3 = readRawByte();
-    byte b4 = readRawByte();
+    final byte b1 = readRawByte();
+    final byte b2 = readRawByte();
+    final byte b3 = readRawByte();
+    final byte b4 = readRawByte();
     return (((int)b1 & 0xff)      ) |
            (((int)b2 & 0xff) <<  8) |
            (((int)b3 & 0xff) << 16) |
@@ -443,14 +409,14 @@
 
   /** Read a 64-bit little-endian integer from the stream. */
   public long readRawLittleEndian64() throws IOException {
-    byte b1 = readRawByte();
-    byte b2 = readRawByte();
-    byte b3 = readRawByte();
-    byte b4 = readRawByte();
-    byte b5 = readRawByte();
-    byte b6 = readRawByte();
-    byte b7 = readRawByte();
-    byte b8 = readRawByte();
+    final byte b1 = readRawByte();
+    final byte b2 = readRawByte();
+    final byte b3 = readRawByte();
+    final byte b4 = readRawByte();
+    final byte b5 = readRawByte();
+    final byte b6 = readRawByte();
+    final byte b7 = readRawByte();
+    final byte b8 = readRawByte();
     return (((long)b1 & 0xff)      ) |
            (((long)b2 & 0xff) <<  8) |
            (((long)b3 & 0xff) << 16) |
@@ -471,7 +437,7 @@
    *          Java has no explicit unsigned support.
    * @return A signed 32-bit integer.
    */
-  public static int decodeZigZag32(int n) {
+  public static int decodeZigZag32(final int n) {
     return (n >>> 1) ^ -(n & 1);
   }
 
@@ -485,31 +451,31 @@
    *          Java has no explicit unsigned support.
    * @return A signed 64-bit integer.
    */
-  public static long decodeZigZag64(long n) {
+  public static long decodeZigZag64(final long n) {
     return (n >>> 1) ^ -(n & 1);
   }
 
   // -----------------------------------------------------------------
 
-  private byte[] buffer;
+  private final byte[] buffer;
   private int bufferSize;
-  private int bufferSizeAfterLimit = 0;
+  private int bufferSizeAfterLimit;
   private int bufferPos;
-  private InputStream input;
-  private int lastTag = 0;
+  private final InputStream input;
+  private int lastTag;
 
   /**
    * The total number of bytes read before the current buffer.  The total
    * bytes read up to the current position can be computed as
    * {@code totalBytesRetired + bufferPos}.
    */
-  private int totalBytesRetired = 0;
+  private int totalBytesRetired;
 
   /** The absolute position of the end of the current message. */
   private int currentLimit = Integer.MAX_VALUE;
 
   /** See setRecursionLimit() */
-  private int recursionDepth = 0;
+  private int recursionDepth;
   private int recursionLimit = DEFAULT_RECURSION_LIMIT;
 
   /** See setSizeLimit() */
@@ -519,17 +485,17 @@
   private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
   private static final int BUFFER_SIZE = 4096;
 
-  private CodedInputStream(byte[] buffer, int off, int len) {
+  private CodedInputStream(final byte[] buffer, final int off, final int len) {
     this.buffer = buffer;
-    this.bufferSize = off + len;
-    this.bufferPos = off;
-    this.input = null;
+    bufferSize = off + len;
+    bufferPos = off;
+    input = null;
   }
 
-  private CodedInputStream(InputStream input) {
-    this.buffer = new byte[BUFFER_SIZE];
-    this.bufferSize = 0;
-    this.bufferPos = 0;
+  private CodedInputStream(final InputStream input) {
+    buffer = new byte[BUFFER_SIZE];
+    bufferSize = 0;
+    bufferPos = 0;
     this.input = input;
   }
 
@@ -540,12 +506,12 @@
    *
    * @return the old limit.
    */
-  public int setRecursionLimit(int limit) {
+  public int setRecursionLimit(final int limit) {
     if (limit < 0) {
       throw new IllegalArgumentException(
         "Recursion limit cannot be negative: " + limit);
     }
-    int oldLimit = recursionLimit;
+    final int oldLimit = recursionLimit;
     recursionLimit = limit;
     return oldLimit;
   }
@@ -566,12 +532,12 @@
    *
    * @return the old limit.
    */
-  public int setSizeLimit(int limit) {
+  public int setSizeLimit(final int limit) {
     if (limit < 0) {
       throw new IllegalArgumentException(
         "Size limit cannot be negative: " + limit);
     }
-    int oldLimit = sizeLimit;
+    final int oldLimit = sizeLimit;
     sizeLimit = limit;
     return oldLimit;
   }
@@ -594,7 +560,7 @@
       throw InvalidProtocolBufferException.negativeSize();
     }
     byteLimit += totalBytesRetired + bufferPos;
-    int oldLimit = currentLimit;
+    final int oldLimit = currentLimit;
     if (byteLimit > oldLimit) {
       throw InvalidProtocolBufferException.truncatedMessage();
     }
@@ -607,7 +573,7 @@
 
   private void recomputeBufferSizeAfterLimit() {
     bufferSize += bufferSizeAfterLimit;
-    int bufferEnd = totalBytesRetired + bufferSize;
+    final int bufferEnd = totalBytesRetired + bufferSize;
     if (bufferEnd > currentLimit) {
       // Limit is in current buffer.
       bufferSizeAfterLimit = bufferEnd - currentLimit;
@@ -622,7 +588,7 @@
    *
    * @param oldLimit The old limit, as returned by {@code pushLimit}.
    */
-  public void popLimit(int oldLimit) {
+  public void popLimit(final int oldLimit) {
     currentLimit = oldLimit;
     recomputeBufferSizeAfterLimit();
   }
@@ -636,7 +602,7 @@
       return -1;
     }
 
-    int currentAbsolutePosition = totalBytesRetired + bufferPos;
+    final int currentAbsolutePosition = totalBytesRetired + bufferPos;
     return currentLimit - currentAbsolutePosition;
   }
 
@@ -656,7 +622,7 @@
    * or it will throw an exception.  If {@code mustSucceed} is false,
    * refillBuffer() returns false if no more bytes were available.
    */
-  private boolean refillBuffer(boolean mustSucceed) throws IOException {
+  private boolean refillBuffer(final boolean mustSucceed) throws IOException {
     if (bufferPos < bufferSize) {
       throw new IllegalStateException(
         "refillBuffer() called when buffer wasn't empty.");
@@ -689,7 +655,7 @@
       }
     } else {
       recomputeBufferSizeAfterLimit();
-      int totalBytesRead =
+      final int totalBytesRead =
         totalBytesRetired + bufferSize + bufferSizeAfterLimit;
       if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
         throw InvalidProtocolBufferException.sizeLimitExceeded();
@@ -717,7 +683,7 @@
    * @throws InvalidProtocolBufferException The end of the stream or the current
    *                                        limit was reached.
    */
-  public byte[] readRawBytes(int size) throws IOException {
+  public byte[] readRawBytes(final int size) throws IOException {
     if (size < 0) {
       throw InvalidProtocolBufferException.negativeSize();
     }
@@ -731,7 +697,7 @@
 
     if (size <= bufferSize - bufferPos) {
       // We have all the bytes we need already.
-      byte[] bytes = new byte[size];
+      final byte[] bytes = new byte[size];
       System.arraycopy(buffer, bufferPos, bytes, 0, size);
       bufferPos += size;
       return bytes;
@@ -740,7 +706,7 @@
       // of bytes.  We can safely allocate the resulting array ahead of time.
 
       // First copy what we have.
-      byte[] bytes = new byte[size];
+      final byte[] bytes = new byte[size];
       int pos = bufferSize - bufferPos;
       System.arraycopy(buffer, bufferPos, bytes, 0, pos);
       bufferPos = bufferSize;
@@ -772,8 +738,8 @@
 
       // Remember the buffer markers since we'll have to copy the bytes out of
       // it later.
-      int originalBufferPos = bufferPos;
-      int originalBufferSize = bufferSize;
+      final int originalBufferPos = bufferPos;
+      final int originalBufferSize = bufferSize;
 
       // Mark the current buffer consumed.
       totalBytesRetired += bufferSize;
@@ -782,13 +748,13 @@
 
       // Read all the rest of the bytes we need.
       int sizeLeft = size - (originalBufferSize - originalBufferPos);
-      List<byte[]> chunks = new ArrayList<byte[]>();
+      final List<byte[]> chunks = new ArrayList<byte[]>();
 
       while (sizeLeft > 0) {
-        byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
+        final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
         int pos = 0;
         while (pos < chunk.length) {
-          int n = (input == null) ? -1 :
+          final int n = (input == null) ? -1 :
             input.read(chunk, pos, chunk.length - pos);
           if (n == -1) {
             throw InvalidProtocolBufferException.truncatedMessage();
@@ -801,14 +767,14 @@
       }
 
       // OK, got everything.  Now concatenate it all into one buffer.
-      byte[] bytes = new byte[size];
+      final byte[] bytes = new byte[size];
 
       // Start by copying the leftover bytes from this.buffer.
       int pos = originalBufferSize - originalBufferPos;
       System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
 
       // And now all the chunks.
-      for (byte[] chunk : chunks) {
+      for (final byte[] chunk : chunks) {
         System.arraycopy(chunk, 0, bytes, pos, chunk.length);
         pos += chunk.length;
       }
@@ -824,7 +790,7 @@
    * @throws InvalidProtocolBufferException The end of the stream or the current
    *                                        limit was reached.
    */
-  public void skipRawBytes(int size) throws IOException {
+  public void skipRawBytes(final int size) throws IOException {
     if (size < 0) {
       throw InvalidProtocolBufferException.negativeSize();
     }
@@ -848,7 +814,7 @@
 
       // Then skip directly from the InputStream for the rest.
       while (pos < size) {
-        int n = (input == null) ? -1 : (int) input.skip(size - pos);
+        final int n = (input == null) ? -1 : (int) input.skip(size - pos);
         if (n <= 0) {
           throw InvalidProtocolBufferException.truncatedMessage();
         }
diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index 69c22d8..d3907a7 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -32,6 +32,7 @@
 
 import java.io.OutputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 
 /**
  * Encodes and writes protocol message fields.
@@ -55,29 +56,30 @@
   private final OutputStream output;
 
   /**
-   * The buffer size used in {@link #newInstance(java.io.OutputStream)}.
+   * The buffer size used in {@link #newInstance(OutputStream)}.
    */
   public static final int DEFAULT_BUFFER_SIZE = 4096;
 
-  private CodedOutputStream(byte[] buffer, int offset, int length) {
-    this.output = null;
+  private CodedOutputStream(final byte[] buffer, final int offset,
+                            final int length) {
+    output = null;
     this.buffer = buffer;
-    this.position = offset;
-    this.limit = offset + length;
+    position = offset;
+    limit = offset + length;
   }
 
-  private CodedOutputStream(OutputStream output, byte[] buffer) {
+  private CodedOutputStream(final OutputStream output, final byte[] buffer) {
     this.output = output;
     this.buffer = buffer;
-    this.position = 0;
-    this.limit = buffer.length;
+    position = 0;
+    limit = buffer.length;
   }
 
   /**
    * Create a new {@code CodedOutputStream} wrapping the given
    * {@code OutputStream}.
    */
-  public static CodedOutputStream newInstance(OutputStream output) {
+  public static CodedOutputStream newInstance(final OutputStream output) {
     return newInstance(output, DEFAULT_BUFFER_SIZE);
   }
 
@@ -85,8 +87,8 @@
    * Create a new {@code CodedOutputStream} wrapping the given
    * {@code OutputStream} with a given buffer size.
    */
-  public static CodedOutputStream newInstance(OutputStream output,
-      int bufferSize) {
+  public static CodedOutputStream newInstance(final OutputStream output,
+      final int bufferSize) {
     return new CodedOutputStream(output, new byte[bufferSize]);
   }
 
@@ -97,7 +99,7 @@
    * array is faster than writing to an {@code OutputStream}.  See also
    * {@link ByteString#newCodedBuilder}.
    */
-  public static CodedOutputStream newInstance(byte[] flatArray) {
+  public static CodedOutputStream newInstance(final byte[] flatArray) {
     return newInstance(flatArray, 0, flatArray.length);
   }
 
@@ -108,96 +110,115 @@
    * array is faster than writing to an {@code OutputStream}.  See also
    * {@link ByteString#newCodedBuilder}.
    */
-  public static CodedOutputStream newInstance(byte[] flatArray, int offset,
-      int length) {
+  public static CodedOutputStream newInstance(final byte[] flatArray,
+                                              final int offset,
+                                              final int length) {
     return new CodedOutputStream(flatArray, offset, length);
   }
 
   // -----------------------------------------------------------------
 
   /** Write a {@code double} field, including tag, to the stream. */
-  public void writeDouble(int fieldNumber, double value) throws IOException {
+  public void writeDouble(final int fieldNumber, final double value)
+                          throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
     writeDoubleNoTag(value);
   }
 
   /** Write a {@code float} field, including tag, to the stream. */
-  public void writeFloat(int fieldNumber, float value) throws IOException {
+  public void writeFloat(final int fieldNumber, final float value)
+                         throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
     writeFloatNoTag(value);
   }
 
   /** Write a {@code uint64} field, including tag, to the stream. */
-  public void writeUInt64(int fieldNumber, long value) throws IOException {
+  public void writeUInt64(final int fieldNumber, final long value)
+                          throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeUInt64NoTag(value);
   }
 
   /** Write an {@code int64} field, including tag, to the stream. */
-  public void writeInt64(int fieldNumber, long value) throws IOException {
+  public void writeInt64(final int fieldNumber, final long value)
+                         throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeInt64NoTag(value);
   }
 
   /** Write an {@code int32} field, including tag, to the stream. */
-  public void writeInt32(int fieldNumber, int value) throws IOException {
+  public void writeInt32(final int fieldNumber, final int value)
+                         throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeInt32NoTag(value);
   }
 
   /** Write a {@code fixed64} field, including tag, to the stream. */
-  public void writeFixed64(int fieldNumber, long value) throws IOException {
+  public void writeFixed64(final int fieldNumber, final long value)
+                           throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
     writeFixed64NoTag(value);
   }
 
   /** Write a {@code fixed32} field, including tag, to the stream. */
-  public void writeFixed32(int fieldNumber, int value) throws IOException {
+  public void writeFixed32(final int fieldNumber, final int value)
+                           throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
     writeFixed32NoTag(value);
   }
 
   /** Write a {@code bool} field, including tag, to the stream. */
-  public void writeBool(int fieldNumber, boolean value) throws IOException {
+  public void writeBool(final int fieldNumber, final boolean value)
+                        throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeBoolNoTag(value);
   }
 
   /** Write a {@code string} field, including tag, to the stream. */
-  public void writeString(int fieldNumber, String value) throws IOException {
+  public void writeString(final int fieldNumber, final String value)
+                          throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
     writeStringNoTag(value);
   }
 
   /** Write a {@code group} field, including tag, to the stream. */
-  public void writeGroup(int fieldNumber, Message value) throws IOException {
+  public void writeGroup(final int fieldNumber, final MessageLite value)
+                         throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
     writeGroupNoTag(value);
     writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
   }
 
-  /** Write a group represented by an {@link UnknownFieldSet}. */
-  public void writeUnknownGroup(int fieldNumber, UnknownFieldSet value)
-      throws IOException {
-    writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
-    writeUnknownGroupNoTag(value);
-    writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+  /**
+   * Write a group represented by an {@link UnknownFieldSet}.
+   *
+   * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+   *             call {@link #writeGroup}.
+   */
+  @Deprecated
+  public void writeUnknownGroup(final int fieldNumber,
+                                final MessageLite value)
+                                throws IOException {
+    writeGroup(fieldNumber, value);
   }
 
   /** Write an embedded message field, including tag, to the stream. */
-  public void writeMessage(int fieldNumber, Message value) throws IOException {
+  public void writeMessage(final int fieldNumber, final MessageLite value)
+                           throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
     writeMessageNoTag(value);
   }
 
   /** Write a {@code bytes} field, including tag, to the stream. */
-  public void writeBytes(int fieldNumber, ByteString value) throws IOException {
+  public void writeBytes(final int fieldNumber, final ByteString value)
+                         throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
     writeBytesNoTag(value);
   }
 
   /** Write a {@code uint32} field, including tag, to the stream. */
-  public void writeUInt32(int fieldNumber, int value) throws IOException {
+  public void writeUInt32(final int fieldNumber, final int value)
+                          throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeUInt32NoTag(value);
   }
@@ -206,31 +227,36 @@
    * Write an enum field, including tag, to the stream.  Caller is responsible
    * for converting the enum value to its numeric value.
    */
-  public void writeEnum(int fieldNumber, int value) throws IOException {
+  public void writeEnum(final int fieldNumber, final int value)
+                        throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeEnumNoTag(value);
   }
 
   /** Write an {@code sfixed32} field, including tag, to the stream. */
-  public void writeSFixed32(int fieldNumber, int value) throws IOException {
+  public void writeSFixed32(final int fieldNumber, final int value)
+                            throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
     writeSFixed32NoTag(value);
   }
 
   /** Write an {@code sfixed64} field, including tag, to the stream. */
-  public void writeSFixed64(int fieldNumber, long value) throws IOException {
+  public void writeSFixed64(final int fieldNumber, final long value)
+                            throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
     writeSFixed64NoTag(value);
   }
 
   /** Write an {@code sint32} field, including tag, to the stream. */
-  public void writeSInt32(int fieldNumber, int value) throws IOException {
+  public void writeSInt32(final int fieldNumber, final int value)
+                          throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeSInt32NoTag(value);
   }
 
   /** Write an {@code sint64} field, including tag, to the stream. */
-  public void writeSInt64(int fieldNumber, long value) throws IOException {
+  public void writeSInt64(final int fieldNumber, final long value)
+                          throws IOException {
     writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
     writeSInt64NoTag(value);
   }
@@ -239,8 +265,9 @@
    * Write a MessageSet extension field to the stream.  For historical reasons,
    * the wire format differs from normal fields.
    */
-  public void writeMessageSetExtension(int fieldNumber, Message value)
-                                throws IOException {
+  public void writeMessageSetExtension(final int fieldNumber,
+                                       final MessageLite value)
+                                       throws IOException {
     writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
     writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
     writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
@@ -251,7 +278,8 @@
    * Write an unparsed MessageSet extension field to the stream.  For
    * historical reasons, the wire format differs from normal fields.
    */
-  public void writeRawMessageSetExtension(int fieldNumber, ByteString value)
+  public void writeRawMessageSetExtension(final int fieldNumber,
+                                          final ByteString value)
                                           throws IOException {
     writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
     writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
@@ -259,89 +287,30 @@
     writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   }
 
-  /**
-   * Write a field of arbitrary type, including tag, to the stream.
-   *
-   * @param type   The field's type.
-   * @param number The field's number.
-   * @param value  Object representing the field's value.  Must be of the exact
-   *               type which would be returned by
-   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
-   *               this field.
-   */
-  public void writeField(Descriptors.FieldDescriptor.Type type,
-                         int number,
-                         Object value) throws IOException {
-    // Special case for groups, which need a start and end tag; other fields
-    // can just use writeTag() and writeFieldNoTag().
-    if (type == Descriptors.FieldDescriptor.Type.GROUP) {
-      writeGroup(number, (Message) value);
-    } else {
-      writeTag(number, WireFormat.getWireFormatForFieldType(type));
-      writeFieldNoTag(type, value);
-    }
-  }
-
-  /**
-   * Write a field of arbitrary type, without its tag, to the stream.
-   *
-   * @param type The field's type.
-   * @param value  Object representing the field's value.  Must be of the exact
-   *               type which would be returned by
-   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
-   *               this field.
-   */
-  public void writeFieldNoTag(Descriptors.FieldDescriptor.Type type,
-                              Object value) throws IOException {
-    switch (type) {
-      case DOUBLE  : writeDoubleNoTag  ((Double    ) value); break;
-      case FLOAT   : writeFloatNoTag   ((Float     ) value); break;
-      case INT64   : writeInt64NoTag   ((Long      ) value); break;
-      case UINT64  : writeUInt64NoTag  ((Long      ) value); break;
-      case INT32   : writeInt32NoTag   ((Integer   ) value); break;
-      case FIXED64 : writeFixed64NoTag ((Long      ) value); break;
-      case FIXED32 : writeFixed32NoTag ((Integer   ) value); break;
-      case BOOL    : writeBoolNoTag    ((Boolean   ) value); break;
-      case STRING  : writeStringNoTag  ((String    ) value); break;
-      case GROUP   : writeGroupNoTag   ((Message   ) value); break;
-      case MESSAGE : writeMessageNoTag ((Message   ) value); break;
-      case BYTES   : writeBytesNoTag   ((ByteString) value); break;
-      case UINT32  : writeUInt32NoTag  ((Integer   ) value); break;
-      case SFIXED32: writeSFixed32NoTag((Integer   ) value); break;
-      case SFIXED64: writeSFixed64NoTag((Long      ) value); break;
-      case SINT32  : writeSInt32NoTag  ((Integer   ) value); break;
-      case SINT64  : writeSInt64NoTag  ((Long      ) value); break;
-
-      case ENUM:
-        writeEnumNoTag(((Descriptors.EnumValueDescriptor) value).getNumber());
-        break;
-    }
-  }
-
   // -----------------------------------------------------------------
 
   /** Write a {@code double} field to the stream. */
-  public void writeDoubleNoTag(double value) throws IOException {
+  public void writeDoubleNoTag(final double value) throws IOException {
     writeRawLittleEndian64(Double.doubleToRawLongBits(value));
   }
 
   /** Write a {@code float} field to the stream. */
-  public void writeFloatNoTag(float value) throws IOException {
+  public void writeFloatNoTag(final float value) throws IOException {
     writeRawLittleEndian32(Float.floatToRawIntBits(value));
   }
 
   /** Write a {@code uint64} field to the stream. */
-  public void writeUInt64NoTag(long value) throws IOException {
+  public void writeUInt64NoTag(final long value) throws IOException {
     writeRawVarint64(value);
   }
 
   /** Write an {@code int64} field to the stream. */
-  public void writeInt64NoTag(long value) throws IOException {
+  public void writeInt64NoTag(final long value) throws IOException {
     writeRawVarint64(value);
   }
 
   /** Write an {@code int32} field to the stream. */
-  public void writeInt32NoTag(int value) throws IOException {
+  public void writeInt32NoTag(final int value) throws IOException {
     if (value >= 0) {
       writeRawVarint32(value);
     } else {
@@ -351,56 +320,62 @@
   }
 
   /** Write a {@code fixed64} field to the stream. */
-  public void writeFixed64NoTag(long value) throws IOException {
+  public void writeFixed64NoTag(final long value) throws IOException {
     writeRawLittleEndian64(value);
   }
 
   /** Write a {@code fixed32} field to the stream. */
-  public void writeFixed32NoTag(int value) throws IOException {
+  public void writeFixed32NoTag(final int value) throws IOException {
     writeRawLittleEndian32(value);
   }
 
   /** Write a {@code bool} field to the stream. */
-  public void writeBoolNoTag(boolean value) throws IOException {
+  public void writeBoolNoTag(final boolean value) throws IOException {
     writeRawByte(value ? 1 : 0);
   }
 
   /** Write a {@code string} field to the stream. */
-  public void writeStringNoTag(String value) throws IOException {
+  public void writeStringNoTag(final String value) throws IOException {
     // Unfortunately there does not appear to be any way to tell Java to encode
     // UTF-8 directly into our buffer, so we have to let it create its own byte
     // array and then copy.
-    byte[] bytes = value.getBytes("UTF-8");
+    final byte[] bytes = value.getBytes("UTF-8");
     writeRawVarint32(bytes.length);
     writeRawBytes(bytes);
   }
 
   /** Write a {@code group} field to the stream. */
-  public void writeGroupNoTag(Message value) throws IOException {
+  public void writeGroupNoTag(final MessageLite value) throws IOException {
     value.writeTo(this);
   }
 
-  /** Write a group represented by an {@link UnknownFieldSet}. */
-  public void writeUnknownGroupNoTag(UnknownFieldSet value)
+  /**
+   * Write a group represented by an {@link UnknownFieldSet}.
+   *
+   * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+   *             call {@link #writeGroupNoTag}.
+   */
+  @Deprecated
+  public void writeUnknownGroupNoTag(final MessageLite value)
       throws IOException {
-    value.writeTo(this);
+    writeGroupNoTag(value);
   }
 
   /** Write an embedded message field to the stream. */
-  public void writeMessageNoTag(Message value) throws IOException {
+  public void writeMessageNoTag(final MessageLite value) throws IOException {
     writeRawVarint32(value.getSerializedSize());
     value.writeTo(this);
   }
 
   /** Write a {@code bytes} field to the stream. */
-  public void writeBytesNoTag(ByteString value) throws IOException {
-    byte[] bytes = value.toByteArray();
+  public void writeBytesNoTag(final ByteString value) throws IOException {
+    final byte[] bytes = value.toByteArray();
     writeRawVarint32(bytes.length);
     writeRawBytes(bytes);
   }
 
   /** Write a {@code uint32} field to the stream. */
-  public void writeUInt32NoTag(int value) throws IOException {
+  public void writeUInt32NoTag(final int value) throws IOException {
     writeRawVarint32(value);
   }
 
@@ -408,27 +383,27 @@
    * Write an enum field to the stream.  Caller is responsible
    * for converting the enum value to its numeric value.
    */
-  public void writeEnumNoTag(int value) throws IOException {
+  public void writeEnumNoTag(final int value) throws IOException {
     writeRawVarint32(value);
   }
 
   /** Write an {@code sfixed32} field to the stream. */
-  public void writeSFixed32NoTag(int value) throws IOException {
+  public void writeSFixed32NoTag(final int value) throws IOException {
     writeRawLittleEndian32(value);
   }
 
   /** Write an {@code sfixed64} field to the stream. */
-  public void writeSFixed64NoTag(long value) throws IOException {
+  public void writeSFixed64NoTag(final long value) throws IOException {
     writeRawLittleEndian64(value);
   }
 
   /** Write an {@code sint32} field to the stream. */
-  public void writeSInt32NoTag(int value) throws IOException {
+  public void writeSInt32NoTag(final int value) throws IOException {
     writeRawVarint32(encodeZigZag32(value));
   }
 
   /** Write an {@code sint64} field to the stream. */
-  public void writeSInt64NoTag(long value) throws IOException {
+  public void writeSInt64NoTag(final long value) throws IOException {
     writeRawVarint64(encodeZigZag64(value));
   }
 
@@ -438,7 +413,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code double} field, including tag.
    */
-  public static int computeDoubleSize(int fieldNumber, double value) {
+  public static int computeDoubleSize(final int fieldNumber,
+                                      final double value) {
     return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
   }
 
@@ -446,7 +422,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code float} field, including tag.
    */
-  public static int computeFloatSize(int fieldNumber, float value) {
+  public static int computeFloatSize(final int fieldNumber, final float value) {
     return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
   }
 
@@ -454,7 +430,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code uint64} field, including tag.
    */
-  public static int computeUInt64Size(int fieldNumber, long value) {
+  public static int computeUInt64Size(final int fieldNumber, final long value) {
     return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
   }
 
@@ -462,7 +438,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code int64} field, including tag.
    */
-  public static int computeInt64Size(int fieldNumber, long value) {
+  public static int computeInt64Size(final int fieldNumber, final long value) {
     return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
   }
 
@@ -470,7 +446,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code int32} field, including tag.
    */
-  public static int computeInt32Size(int fieldNumber, int value) {
+  public static int computeInt32Size(final int fieldNumber, final int value) {
     return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
   }
 
@@ -478,7 +454,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code fixed64} field, including tag.
    */
-  public static int computeFixed64Size(int fieldNumber, long value) {
+  public static int computeFixed64Size(final int fieldNumber,
+                                       final long value) {
     return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
   }
 
@@ -486,7 +463,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code fixed32} field, including tag.
    */
-  public static int computeFixed32Size(int fieldNumber, int value) {
+  public static int computeFixed32Size(final int fieldNumber,
+                                       final int value) {
     return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
   }
 
@@ -494,7 +472,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code bool} field, including tag.
    */
-  public static int computeBoolSize(int fieldNumber, boolean value) {
+  public static int computeBoolSize(final int fieldNumber,
+                                    final boolean value) {
     return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
   }
 
@@ -502,7 +481,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code string} field, including tag.
    */
-  public static int computeStringSize(int fieldNumber, String value) {
+  public static int computeStringSize(final int fieldNumber,
+                                      final String value) {
     return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
   }
 
@@ -510,7 +490,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code group} field, including tag.
    */
-  public static int computeGroupSize(int fieldNumber, Message value) {
+  public static int computeGroupSize(final int fieldNumber,
+                                     final MessageLite value) {
     return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
   }
 
@@ -518,18 +499,22 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code group} field represented by an {@code UnknownFieldSet}, including
    * tag.
+   *
+   * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+   *             call {@link #computeGroupSize}.
    */
-  public static int computeUnknownGroupSize(int fieldNumber,
-                                            UnknownFieldSet value) {
-    return computeTagSize(fieldNumber) * 2 +
-        computeUnknownGroupSizeNoTag(value);
+  @Deprecated
+  public static int computeUnknownGroupSize(final int fieldNumber,
+                                            final MessageLite value) {
+    return computeGroupSize(fieldNumber, value);
   }
 
   /**
    * Compute the number of bytes that would be needed to encode an
    * embedded message field, including tag.
    */
-  public static int computeMessageSize(int fieldNumber, Message value) {
+  public static int computeMessageSize(final int fieldNumber,
+                                       final MessageLite value) {
     return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
   }
 
@@ -537,7 +522,8 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code bytes} field, including tag.
    */
-  public static int computeBytesSize(int fieldNumber, ByteString value) {
+  public static int computeBytesSize(final int fieldNumber,
+                                     final ByteString value) {
     return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
   }
 
@@ -545,7 +531,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code uint32} field, including tag.
    */
-  public static int computeUInt32Size(int fieldNumber, int value) {
+  public static int computeUInt32Size(final int fieldNumber, final int value) {
     return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
   }
 
@@ -554,7 +540,7 @@
    * enum field, including tag.  Caller is responsible for converting the
    * enum value to its numeric value.
    */
-  public static int computeEnumSize(int fieldNumber, int value) {
+  public static int computeEnumSize(final int fieldNumber, final int value) {
     return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
   }
 
@@ -562,7 +548,8 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sfixed32} field, including tag.
    */
-  public static int computeSFixed32Size(int fieldNumber, int value) {
+  public static int computeSFixed32Size(final int fieldNumber,
+                                        final int value) {
     return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
   }
 
@@ -570,7 +557,8 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sfixed64} field, including tag.
    */
-  public static int computeSFixed64Size(int fieldNumber, long value) {
+  public static int computeSFixed64Size(final int fieldNumber,
+                                        final long value) {
     return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
   }
 
@@ -578,7 +566,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sint32} field, including tag.
    */
-  public static int computeSInt32Size(int fieldNumber, int value) {
+  public static int computeSInt32Size(final int fieldNumber, final int value) {
     return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
   }
 
@@ -586,7 +574,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sint64} field, including tag.
    */
-  public static int computeSInt64Size(int fieldNumber, long value) {
+  public static int computeSInt64Size(final int fieldNumber, final long value) {
     return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
   }
 
@@ -596,7 +584,7 @@
    * the wire format differs from normal fields.
    */
   public static int computeMessageSetExtensionSize(
-      int fieldNumber, Message value) {
+      final int fieldNumber, final MessageLite value) {
     return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
            computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
            computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);
@@ -608,7 +596,7 @@
    * historical reasons, the wire format differs from normal fields.
    */
   public static int computeRawMessageSetExtensionSize(
-      int fieldNumber, ByteString value) {
+      final int fieldNumber, final ByteString value) {
     return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
            computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
            computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
@@ -620,7 +608,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code double} field, including tag.
    */
-  public static int computeDoubleSizeNoTag(double value) {
+  public static int computeDoubleSizeNoTag(final double value) {
     return LITTLE_ENDIAN_64_SIZE;
   }
 
@@ -628,7 +616,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code float} field, including tag.
    */
-  public static int computeFloatSizeNoTag(float value) {
+  public static int computeFloatSizeNoTag(final float value) {
     return LITTLE_ENDIAN_32_SIZE;
   }
 
@@ -636,7 +624,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code uint64} field, including tag.
    */
-  public static int computeUInt64SizeNoTag(long value) {
+  public static int computeUInt64SizeNoTag(final long value) {
     return computeRawVarint64Size(value);
   }
 
@@ -644,7 +632,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code int64} field, including tag.
    */
-  public static int computeInt64SizeNoTag(long value) {
+  public static int computeInt64SizeNoTag(final long value) {
     return computeRawVarint64Size(value);
   }
 
@@ -652,7 +640,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code int32} field, including tag.
    */
-  public static int computeInt32SizeNoTag(int value) {
+  public static int computeInt32SizeNoTag(final int value) {
     if (value >= 0) {
       return computeRawVarint32Size(value);
     } else {
@@ -665,7 +653,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code fixed64} field.
    */
-  public static int computeFixed64SizeNoTag(long value) {
+  public static int computeFixed64SizeNoTag(final long value) {
     return LITTLE_ENDIAN_64_SIZE;
   }
 
@@ -673,7 +661,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code fixed32} field.
    */
-  public static int computeFixed32SizeNoTag(int value) {
+  public static int computeFixed32SizeNoTag(final int value) {
     return LITTLE_ENDIAN_32_SIZE;
   }
 
@@ -681,7 +669,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code bool} field.
    */
-  public static int computeBoolSizeNoTag(boolean value) {
+  public static int computeBoolSizeNoTag(final boolean value) {
     return 1;
   }
 
@@ -689,12 +677,12 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code string} field.
    */
-  public static int computeStringSizeNoTag(String value) {
+  public static int computeStringSizeNoTag(final String value) {
     try {
-      byte[] bytes = value.getBytes("UTF-8");
+      final byte[] bytes = value.getBytes("UTF-8");
       return computeRawVarint32Size(bytes.length) +
              bytes.length;
-    } catch (java.io.UnsupportedEncodingException e) {
+    } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported.", e);
     }
   }
@@ -703,7 +691,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code group} field.
    */
-  public static int computeGroupSizeNoTag(Message value) {
+  public static int computeGroupSizeNoTag(final MessageLite value) {
     return value.getSerializedSize();
   }
 
@@ -711,17 +699,21 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code group} field represented by an {@code UnknownFieldSet}, including
    * tag.
+   *
+   * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+   *             call {@link #computeUnknownGroupSizeNoTag}.
    */
-  public static int computeUnknownGroupSizeNoTag(UnknownFieldSet value) {
-    return value.getSerializedSize();
+  @Deprecated
+  public static int computeUnknownGroupSizeNoTag(final MessageLite value) {
+    return computeGroupSizeNoTag(value);
   }
 
   /**
    * Compute the number of bytes that would be needed to encode an embedded
    * message field.
    */
-  public static int computeMessageSizeNoTag(Message value) {
-    int size = value.getSerializedSize();
+  public static int computeMessageSizeNoTag(final MessageLite value) {
+    final int size = value.getSerializedSize();
     return computeRawVarint32Size(size) + size;
   }
 
@@ -729,7 +721,7 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code bytes} field.
    */
-  public static int computeBytesSizeNoTag(ByteString value) {
+  public static int computeBytesSizeNoTag(final ByteString value) {
     return computeRawVarint32Size(value.size()) +
            value.size();
   }
@@ -738,15 +730,15 @@
    * Compute the number of bytes that would be needed to encode a
    * {@code uint32} field.
    */
-  public static int computeUInt32SizeNoTag(int value) {
+  public static int computeUInt32SizeNoTag(final int value) {
     return computeRawVarint32Size(value);
   }
 
   /**
-   * Compute the number of bytes that would be needed to encode an enum field.  
+   * Compute the number of bytes that would be needed to encode an enum field.
    * Caller is responsible for converting the enum value to its numeric value.
    */
-  public static int computeEnumSizeNoTag(int value) {
+  public static int computeEnumSizeNoTag(final int value) {
     return computeRawVarint32Size(value);
   }
 
@@ -754,7 +746,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sfixed32} field.
    */
-  public static int computeSFixed32SizeNoTag(int value) {
+  public static int computeSFixed32SizeNoTag(final int value) {
     return LITTLE_ENDIAN_32_SIZE;
   }
 
@@ -762,7 +754,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sfixed64} field.
    */
-  public static int computeSFixed64SizeNoTag(long value) {
+  public static int computeSFixed64SizeNoTag(final long value) {
     return LITTLE_ENDIAN_64_SIZE;
   }
 
@@ -770,7 +762,7 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sint32} field.
    */
-  public static int computeSInt32SizeNoTag(int value) {
+  public static int computeSInt32SizeNoTag(final int value) {
     return computeRawVarint32Size(encodeZigZag32(value));
   }
 
@@ -778,71 +770,10 @@
    * Compute the number of bytes that would be needed to encode an
    * {@code sint64} field.
    */
-  public static int computeSInt64SizeNoTag(long value) {
+  public static int computeSInt64SizeNoTag(final long value) {
     return computeRawVarint64Size(encodeZigZag64(value));
   }
 
-  /**
-   * Compute the number of bytes that would be needed to encode a
-   * field of arbitrary type, including tag, to the stream.
-   *
-   * @param type   The field's type.
-   * @param number The field's number.
-   * @param value  Object representing the field's value.  Must be of the exact
-   *               type which would be returned by
-   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
-   *               this field.
-   */
-  public static int computeFieldSize(
-      Descriptors.FieldDescriptor.Type type,
-      int number, Object value) {
-    int tagSize = computeTagSize(number);
-    if (type == Descriptors.FieldDescriptor.Type.GROUP) {
-      tagSize *= 2;
-    }
-    return tagSize + computeFieldSizeNoTag(type, value);
-  }
-
-  /**
-   * Compute the number of bytes that would be needed to encode a
-   * field of arbitrary type, excluding tag, to the stream.
-   *
-   * @param type   The field's type.
-   * @param value  Object representing the field's value.  Must be of the exact
-   *               type which would be returned by
-   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
-   *               this field.
-   */
-  public static int computeFieldSizeNoTag(
-      Descriptors.FieldDescriptor.Type type, Object value) {
-    switch (type) {
-      case DOUBLE  : return computeDoubleSizeNoTag  ((Double    )value);
-      case FLOAT   : return computeFloatSizeNoTag   ((Float     )value);
-      case INT64   : return computeInt64SizeNoTag   ((Long      )value);
-      case UINT64  : return computeUInt64SizeNoTag  ((Long      )value);
-      case INT32   : return computeInt32SizeNoTag   ((Integer   )value);
-      case FIXED64 : return computeFixed64SizeNoTag ((Long      )value);
-      case FIXED32 : return computeFixed32SizeNoTag ((Integer   )value);
-      case BOOL    : return computeBoolSizeNoTag    ((Boolean   )value);
-      case STRING  : return computeStringSizeNoTag  ((String    )value);
-      case GROUP   : return computeGroupSizeNoTag   ((Message   )value);
-      case MESSAGE : return computeMessageSizeNoTag ((Message   )value);
-      case BYTES   : return computeBytesSizeNoTag   ((ByteString)value);
-      case UINT32  : return computeUInt32SizeNoTag  ((Integer   )value);
-      case SFIXED32: return computeSFixed32SizeNoTag((Integer   )value);
-      case SFIXED64: return computeSFixed64SizeNoTag((Long      )value);
-      case SINT32  : return computeSInt32SizeNoTag  ((Integer   )value);
-      case SINT64  : return computeSInt64SizeNoTag  ((Long      )value);
-
-      case ENUM:
-        return computeEnumSizeNoTag(
-            ((Descriptors.EnumValueDescriptor)value).getNumber());
-    }
-
-    throw new RuntimeException(
-      "There is no way to get here, but the compiler thinks otherwise.");
-  }
-
   // =================================================================
 
   /**
@@ -905,6 +836,8 @@
    * this exception will be thrown.
    */
   public static class OutOfSpaceException extends IOException {
+    private static final long serialVersionUID = -6947486886997889499L;
+
     OutOfSpaceException() {
       super("CodedOutputStream was writing to a flat byte array and ran " +
             "out of space.");
@@ -912,7 +845,7 @@
   }
 
   /** Write a single byte. */
-  public void writeRawByte(byte value) throws IOException {
+  public void writeRawByte(final byte value) throws IOException {
     if (position == limit) {
       refreshBuffer();
     }
@@ -921,17 +854,17 @@
   }
 
   /** Write a single byte, represented by an integer value. */
-  public void writeRawByte(int value) throws IOException {
+  public void writeRawByte(final int value) throws IOException {
     writeRawByte((byte) value);
   }
 
   /** Write an array of bytes. */
-  public void writeRawBytes(byte[] value) throws IOException {
+  public void writeRawBytes(final byte[] value) throws IOException {
     writeRawBytes(value, 0, value.length);
   }
 
   /** Write part of an array of bytes. */
-  public void writeRawBytes(byte[] value, int offset, int length)
+  public void writeRawBytes(final byte[] value, int offset, int length)
                             throws IOException {
     if (limit - position >= length) {
       // We have room in the current buffer.
@@ -940,7 +873,7 @@
     } else {
       // Write extends past current buffer.  Fill the rest of this buffer and
       // flush.
-      int bytesWritten = limit - position;
+      final int bytesWritten = limit - position;
       System.arraycopy(value, offset, buffer, position, bytesWritten);
       offset += bytesWritten;
       length -= bytesWritten;
@@ -962,12 +895,13 @@
   }
 
   /** Encode and write a tag. */
-  public void writeTag(int fieldNumber, int wireType) throws IOException {
+  public void writeTag(final int fieldNumber, final int wireType)
+                       throws IOException {
     writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
   }
 
   /** Compute the number of bytes that would be needed to encode a tag. */
-  public static int computeTagSize(int fieldNumber) {
+  public static int computeTagSize(final int fieldNumber) {
     return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
   }
 
@@ -992,7 +926,7 @@
    * {@code value} is treated as unsigned, so it won't be sign-extended if
    * negative.
    */
-  public static int computeRawVarint32Size(int value) {
+  public static int computeRawVarint32Size(final int value) {
     if ((value & (0xffffffff <<  7)) == 0) return 1;
     if ((value & (0xffffffff << 14)) == 0) return 2;
     if ((value & (0xffffffff << 21)) == 0) return 3;
@@ -1014,7 +948,7 @@
   }
 
   /** Compute the number of bytes that would be needed to encode a varint. */
-  public static int computeRawVarint64Size(long value) {
+  public static int computeRawVarint64Size(final long value) {
     if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
     if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
     if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
@@ -1028,7 +962,7 @@
   }
 
   /** Write a little-endian 32-bit integer. */
-  public void writeRawLittleEndian32(int value) throws IOException {
+  public void writeRawLittleEndian32(final int value) throws IOException {
     writeRawByte((value      ) & 0xFF);
     writeRawByte((value >>  8) & 0xFF);
     writeRawByte((value >> 16) & 0xFF);
@@ -1038,7 +972,7 @@
   public static final int LITTLE_ENDIAN_32_SIZE = 4;
 
   /** Write a little-endian 64-bit integer. */
-  public void writeRawLittleEndian64(long value) throws IOException {
+  public void writeRawLittleEndian64(final long value) throws IOException {
     writeRawByte((int)(value      ) & 0xFF);
     writeRawByte((int)(value >>  8) & 0xFF);
     writeRawByte((int)(value >> 16) & 0xFF);
@@ -1061,7 +995,7 @@
    * @return An unsigned 32-bit integer, stored in a signed int because
    *         Java has no explicit unsigned support.
    */
-  public static int encodeZigZag32(int n) {
+  public static int encodeZigZag32(final int n) {
     // Note:  the right-shift must be arithmetic
     return (n << 1) ^ (n >> 31);
   }
@@ -1076,7 +1010,7 @@
    * @return An unsigned 64-bit integer, stored in a signed int because
    *         Java has no explicit unsigned support.
    */
-  public static long encodeZigZag64(long n) {
+  public static long encodeZigZag64(final long n) {
     // Note:  the right-shift must be arithmetic
     return (n << 1) ^ (n >> 63);
   }
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 24499ef..0d5e47d 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -37,11 +37,12 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.io.UnsupportedEncodingException;
 
 /**
  * Contains a collection of classes which describe protocol message types.
  *
- * Every message type has a {@link Descriptors.Descriptor}, which lists all
+ * Every message type has a {@link Descriptor}, which lists all
  * its fields and other information about a type.  You can get a message
  * type's descriptor by calling {@code MessageType.getDescriptor()}, or
  * (given a message object of the type) {@code message.getDescriptorForType()}.
@@ -106,11 +107,13 @@
     public Descriptor findMessageTypeByName(String name) {
       // Don't allow looking up nested types.  This will make optimization
       // easier later.
-      if (name.indexOf('.') != -1) return null;
-      if (getPackage().length() > 0) {
-        name = getPackage() + "." + name;
+      if (name.indexOf('.') != -1) {
+        return null;
       }
-      GenericDescriptor result = pool.findSymbol(name);
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
       if (result != null && result instanceof Descriptor &&
           result.getFile() == this) {
         return (Descriptor)result;
@@ -128,11 +131,13 @@
     public EnumDescriptor findEnumTypeByName(String name) {
       // Don't allow looking up nested types.  This will make optimization
       // easier later.
-      if (name.indexOf('.') != -1) return null;
-      if (getPackage().length() > 0) {
-        name = getPackage() + "." + name;
+      if (name.indexOf('.') != -1) {
+        return null;
       }
-      GenericDescriptor result = pool.findSymbol(name);
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
       if (result != null && result instanceof EnumDescriptor &&
           result.getFile() == this) {
         return (EnumDescriptor)result;
@@ -150,11 +155,13 @@
     public ServiceDescriptor findServiceByName(String name) {
       // Don't allow looking up nested types.  This will make optimization
       // easier later.
-      if (name.indexOf('.') != -1) return null;
-      if (getPackage().length() > 0) {
-        name = getPackage() + "." + name;
+      if (name.indexOf('.') != -1) {
+        return null;
       }
-      GenericDescriptor result = pool.findSymbol(name);
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
       if (result != null && result instanceof ServiceDescriptor &&
           result.getFile() == this) {
         return (ServiceDescriptor)result;
@@ -171,11 +178,13 @@
      * @return The extension's descriptor, or {@code null} if not found.
      */
     public FieldDescriptor findExtensionByName(String name) {
-      if (name.indexOf('.') != -1) return null;
-      if (getPackage().length() > 0) {
-        name = getPackage() + "." + name;
+      if (name.indexOf('.') != -1) {
+        return null;
       }
-      GenericDescriptor result = pool.findSymbol(name);
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
       if (result != null && result instanceof FieldDescriptor &&
           result.getFile() == this) {
         return (FieldDescriptor)result;
@@ -196,8 +205,8 @@
      *           because a field has an undefined type or because two messages
      *           were defined with the same name.
      */
-    public static FileDescriptor buildFrom(FileDescriptorProto proto,
-                                           FileDescriptor[] dependencies)
+    public static FileDescriptor buildFrom(final FileDescriptorProto proto,
+                                           final FileDescriptor[] dependencies)
                                     throws DescriptorValidationException {
       // Building decsriptors involves two steps:  translating and linking.
       // In the translation step (implemented by FileDescriptor's
@@ -208,8 +217,9 @@
       // FieldDescriptor for an embedded message contains a pointer directly
       // to the Descriptor for that message's type.  We also detect undefined
       // types in the linking step.
-      DescriptorPool pool = new DescriptorPool(dependencies);
-      FileDescriptor result = new FileDescriptor(proto, dependencies, pool);
+      final DescriptorPool pool = new DescriptorPool(dependencies);
+      final FileDescriptor result =
+          new FileDescriptor(proto, dependencies, pool);
 
       if (dependencies.length != proto.getDependencyCount()) {
         throw new DescriptorValidationException(result,
@@ -234,8 +244,8 @@
      * encoded in protocol buffer wire format.
      */
     public static void internalBuildGeneratedFileFrom(
-        String descriptorData, FileDescriptor[] dependencies,
-        InternalDescriptorAssigner descriptorAssigner) {
+        final String descriptorData, final FileDescriptor[] dependencies,
+        final InternalDescriptorAssigner descriptorAssigner) {
       // Hack:  We can't embed a raw byte array inside generated Java code
       //   (at least, not efficiently), but we can embed Strings.  So, the
       //   protocol compiler embeds the FileDescriptorProto as a giant
@@ -245,10 +255,10 @@
       //   serialized form.  So, if we convert it to bytes in ISO-8859-1, we
       //   should get the original bytes that we want.
 
-      byte[] descriptorBytes;
+      final byte[] descriptorBytes;
       try {
         descriptorBytes = descriptorData.getBytes("ISO-8859-1");
-      } catch (java.io.UnsupportedEncodingException e) {
+      } catch (UnsupportedEncodingException e) {
         throw new RuntimeException(
           "Standard encoding ISO-8859-1 not supported by JVM.", e);
       }
@@ -261,7 +271,7 @@
           "Failed to parse protocol buffer descriptor for generated code.", e);
       }
 
-      FileDescriptor result;
+      final FileDescriptor result;
       try {
         result = buildFrom(proto, dependencies);
       } catch (DescriptorValidationException e) {
@@ -269,7 +279,8 @@
           "Invalid embedded descriptor for \"" + proto.getName() + "\".", e);
       }
 
-      ExtensionRegistry registry = descriptorAssigner.assignDescriptors(result);
+      final ExtensionRegistry registry =
+          descriptorAssigner.assignDescriptors(result);
 
       if (registry != null) {
         // We must re-parse the proto using the registry.
@@ -297,7 +308,7 @@
      * descriptor.proto.  The callback may also return null to indicate that
      * no extensions are used in the decsriptor.
      */
-    public static interface InternalDescriptorAssigner {
+    public interface InternalDescriptorAssigner {
       ExtensionRegistry assignDescriptors(FileDescriptor root);
     }
 
@@ -309,9 +320,9 @@
     private final FileDescriptor[] dependencies;
     private final DescriptorPool pool;
 
-    private FileDescriptor(FileDescriptorProto proto,
-                           FileDescriptor[] dependencies,
-                           DescriptorPool pool)
+    private FileDescriptor(final FileDescriptorProto proto,
+                           final FileDescriptor[] dependencies,
+                           final DescriptorPool pool)
                     throws DescriptorValidationException {
       this.pool = pool;
       this.proto = proto;
@@ -344,16 +355,16 @@
 
     /** Look up and cross-link all field types, etc. */
     private void crossLink() throws DescriptorValidationException {
-      for (int i = 0; i < messageTypes.length; i++) {
-        messageTypes[i].crossLink();
+      for (final Descriptor messageType : messageTypes) {
+        messageType.crossLink();
       }
 
-      for (int i = 0; i < services.length; i++) {
-        services[i].crossLink();
+      for (final ServiceDescriptor service : services) {
+        service.crossLink();
       }
 
-      for (int i = 0; i < extensions.length; i++) {
-        extensions[i].crossLink();
+      for (final FieldDescriptor extension : extensions) {
+        extension.crossLink();
       }
     }
 
@@ -367,7 +378,7 @@
      * protos.  So, we have to parse the descriptor protos a second time after
      * constructing the descriptors.
      */
-    private void setProto(FileDescriptorProto proto) {
+    private void setProto(final FileDescriptorProto proto) {
       this.proto = proto;
 
       for (int i = 0; i < messageTypes.length; i++) {
@@ -456,8 +467,9 @@
     }
 
     /** Determines if the given field number is an extension. */
-    public boolean isExtensionNumber(int number) {
-      for (DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
+    public boolean isExtensionNumber(final int number) {
+      for (final DescriptorProto.ExtensionRange range :
+          proto.getExtensionRangeList()) {
         if (range.getStart() <= number && number < range.getEnd()) {
           return true;
         }
@@ -470,8 +482,9 @@
      * @param name The unqualified name of the field (e.g. "foo").
      * @return The field's descriptor, or {@code null} if not found.
      */
-    public FieldDescriptor findFieldByName(String name) {
-      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+    public FieldDescriptor findFieldByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
       if (result != null && result instanceof FieldDescriptor) {
         return (FieldDescriptor)result;
       } else {
@@ -484,7 +497,7 @@
      * @param number The field number within this message type.
      * @return The field's descriptor, or {@code null} if not found.
      */
-    public FieldDescriptor findFieldByNumber(int number) {
+    public FieldDescriptor findFieldByNumber(final int number) {
       return file.pool.fieldsByNumber.get(
         new DescriptorPool.DescriptorIntPair(this, number));
     }
@@ -494,8 +507,9 @@
      * @param name The unqualified name of the nested type (e.g. "Foo").
      * @return The types's descriptor, or {@code null} if not found.
      */
-    public Descriptor findNestedTypeByName(String name) {
-      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+    public Descriptor findNestedTypeByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
       if (result != null && result instanceof Descriptor) {
         return (Descriptor)result;
       } else {
@@ -508,8 +522,9 @@
      * @param name The unqualified name of the nested type (e.g. "Foo").
      * @return The types's descriptor, or {@code null} if not found.
      */
-    public EnumDescriptor findEnumTypeByName(String name) {
-      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+    public EnumDescriptor findEnumTypeByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
       if (result != null && result instanceof EnumDescriptor) {
         return (EnumDescriptor)result;
       } else {
@@ -527,38 +542,38 @@
     private final FieldDescriptor[] fields;
     private final FieldDescriptor[] extensions;
 
-    private Descriptor(DescriptorProto proto,
-                       FileDescriptor file,
-                       Descriptor parent,
-                       int index)
+    private Descriptor(final DescriptorProto proto,
+                       final FileDescriptor file,
+                       final Descriptor parent,
+                       final int index)
                 throws DescriptorValidationException {
       this.index = index;
       this.proto = proto;
-      this.fullName = computeFullName(file, parent, proto.getName());
+      fullName = computeFullName(file, parent, proto.getName());
       this.file = file;
-      this.containingType = parent;
+      containingType = parent;
 
-      this.nestedTypes = new Descriptor[proto.getNestedTypeCount()];
+      nestedTypes = new Descriptor[proto.getNestedTypeCount()];
       for (int i = 0; i < proto.getNestedTypeCount(); i++) {
-        this.nestedTypes[i] = new Descriptor(
+        nestedTypes[i] = new Descriptor(
           proto.getNestedType(i), file, this, i);
       }
 
-      this.enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
+      enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
       for (int i = 0; i < proto.getEnumTypeCount(); i++) {
-        this.enumTypes[i] = new EnumDescriptor(
+        enumTypes[i] = new EnumDescriptor(
           proto.getEnumType(i), file, this, i);
       }
 
-      this.fields = new FieldDescriptor[proto.getFieldCount()];
+      fields = new FieldDescriptor[proto.getFieldCount()];
       for (int i = 0; i < proto.getFieldCount(); i++) {
-        this.fields[i] = new FieldDescriptor(
+        fields[i] = new FieldDescriptor(
           proto.getField(i), file, this, i, false);
       }
 
-      this.extensions = new FieldDescriptor[proto.getExtensionCount()];
+      extensions = new FieldDescriptor[proto.getExtensionCount()];
       for (int i = 0; i < proto.getExtensionCount(); i++) {
-        this.extensions[i] = new FieldDescriptor(
+        extensions[i] = new FieldDescriptor(
           proto.getExtension(i), file, this, i, true);
       }
 
@@ -567,21 +582,21 @@
 
     /** Look up and cross-link all field types, etc. */
     private void crossLink() throws DescriptorValidationException {
-      for (int i = 0; i < nestedTypes.length; i++) {
-        nestedTypes[i].crossLink();
+      for (final Descriptor nestedType : nestedTypes) {
+        nestedType.crossLink();
       }
 
-      for (int i = 0; i < fields.length; i++) {
-        fields[i].crossLink();
+      for (final FieldDescriptor field : fields) {
+        field.crossLink();
       }
 
-      for (int i = 0; i < extensions.length; i++) {
-        extensions[i].crossLink();
+      for (final FieldDescriptor extension : extensions) {
+        extension.crossLink();
       }
     }
 
-    /** See {@link FileDescriptor.setProto}. */
-    private void setProto(DescriptorProto proto) {
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final DescriptorProto proto) {
       this.proto = proto;
 
       for (int i = 0; i < nestedTypes.length; i++) {
@@ -606,10 +621,11 @@
 
   /** Describes a field of a message type. */
   public static final class FieldDescriptor
-      implements GenericDescriptor, Comparable<FieldDescriptor> {
+      implements GenericDescriptor, Comparable<FieldDescriptor>,
+                 FieldSet.FieldDescriptorLite<FieldDescriptor> {
     /**
      * Get the index of this descriptor within its parent.
-     * @see Descriptors.Descriptor#getIndex()
+     * @see Descriptor#getIndex()
      */
     public int getIndex() { return index; }
 
@@ -624,7 +640,7 @@
 
     /**
      * Get the field's fully-qualified name.
-     * @see Descriptors.Descriptor#getFullName()
+     * @see Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -634,12 +650,27 @@
      */
     public JavaType getJavaType() { return type.getJavaType(); }
 
+    /** For internal use only. */
+    public WireFormat.JavaType getLiteJavaType() {
+      return getLiteType().getJavaType();
+    }
+
     /** Get the {@code FileDescriptor} containing this descriptor. */
     public FileDescriptor getFile() { return file; }
 
     /** Get the field's declared type. */
     public Type getType() { return type; }
 
+    /** For internal use only. */
+    public WireFormat.FieldType getLiteType() {
+      return table[type.ordinal()];
+    }
+    // I'm pretty sure values() constructs a new array every time, since there
+    // is nothing stopping the caller from mutating the array.  Therefore we
+    // make a static copy here.
+    private static final WireFormat.FieldType[] table =
+        WireFormat.FieldType.values();
+
     /** Is this field declared required? */
     public boolean isRequired() {
       return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
@@ -655,6 +686,11 @@
       return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
     }
 
+    /** Does this field have the {@code [packed = true]} option? */
+    public boolean isPacked() {
+      return getOptions().getPacked();
+    }
+
     /** Returns true if the field had an explicitly-defined default value. */
     public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
 
@@ -742,7 +778,7 @@
      * @return negative, zero, or positive if {@code this} is less than,
      *         equal to, or greater than {@code other}, respectively.
      */
-    public int compareTo(FieldDescriptor other) {
+    public int compareTo(final FieldDescriptor other) {
       if (other.containingType != containingType) {
         throw new IllegalArgumentException(
           "FieldDescriptors can only be compared to other FieldDescriptors " +
@@ -765,7 +801,7 @@
     private EnumDescriptor enumType;
     private Object defaultValue;
 
-    public static enum Type {
+    public enum Type {
       DOUBLE  (FieldDescriptorProto.Type.TYPE_DOUBLE  , JavaType.DOUBLE     ),
       FLOAT   (FieldDescriptorProto.Type.TYPE_FLOAT   , JavaType.FLOAT      ),
       INT64   (FieldDescriptorProto.Type.TYPE_INT64   , JavaType.LONG       ),
@@ -785,11 +821,11 @@
       SINT32  (FieldDescriptorProto.Type.TYPE_SINT32  , JavaType.INT        ),
       SINT64  (FieldDescriptorProto.Type.TYPE_SINT64  , JavaType.LONG       );
 
-      private Type(FieldDescriptorProto.Type proto, JavaType javaType) {
+      Type(final FieldDescriptorProto.Type proto, final JavaType javaType) {
         this.proto = proto;
         this.javaType = javaType;
 
-        if (this.ordinal() != proto.getNumber() - 1) {
+        if (ordinal() != proto.getNumber() - 1) {
           throw new RuntimeException(
             "descriptor.proto changed but Desrciptors.java wasn't updated.");
         }
@@ -801,7 +837,7 @@
       public FieldDescriptorProto.Type toProto() { return proto; }
       public JavaType getJavaType() { return javaType; }
 
-      public static Type valueOf(FieldDescriptorProto.Type type) {
+      public static Type valueOf(final FieldDescriptorProto.Type type) {
         return values()[type.getNumber() - 1];
       }
     }
@@ -815,7 +851,7 @@
       }
     }
 
-    public static enum JavaType {
+    public enum JavaType {
       INT(0),
       LONG(0L),
       FLOAT(0F),
@@ -826,7 +862,7 @@
       ENUM(null),
       MESSAGE(null);
 
-      private JavaType(Object defaultDefault) {
+      JavaType(final Object defaultDefault) {
         this.defaultDefault = defaultDefault;
       }
 
@@ -834,22 +870,22 @@
        * The default default value for fields of this type, if it's a primitive
        * type.  This is meant for use inside this file only, hence is private.
        */
-      private Object defaultDefault;
+      private final Object defaultDefault;
     }
 
-    private FieldDescriptor(FieldDescriptorProto proto,
-                            FileDescriptor file,
-                            Descriptor parent,
-                            int index,
-                            boolean isExtension)
+    private FieldDescriptor(final FieldDescriptorProto proto,
+                            final FileDescriptor file,
+                            final Descriptor parent,
+                            final int index,
+                            final boolean isExtension)
                      throws DescriptorValidationException {
       this.index = index;
       this.proto = proto;
-      this.fullName = computeFullName(file, parent, proto.getName());
+      fullName = computeFullName(file, parent, proto.getName());
       this.file = file;
 
       if (proto.hasType()) {
-        this.type = Type.valueOf(proto.getType());
+        type = Type.valueOf(proto.getType());
       }
 
       if (getNumber() <= 0) {
@@ -875,19 +911,19 @@
           throw new DescriptorValidationException(this,
             "FieldDescriptorProto.extendee not set for extension field.");
         }
-        this.containingType = null;  // Will be filled in when cross-linking
+        containingType = null;  // Will be filled in when cross-linking
         if (parent != null) {
-          this.extensionScope = parent;
+          extensionScope = parent;
         } else {
-          this.extensionScope = null;
+          extensionScope = null;
         }
       } else {
         if (proto.hasExtendee()) {
           throw new DescriptorValidationException(this,
             "FieldDescriptorProto.extendee set for non-extension field.");
         }
-        this.containingType = parent;
-        this.extensionScope = null;
+        containingType = parent;
+        extensionScope = null;
       }
 
       file.pool.addSymbol(this);
@@ -896,43 +932,44 @@
     /** Look up and cross-link all field types, etc. */
     private void crossLink() throws DescriptorValidationException {
       if (proto.hasExtendee()) {
-        GenericDescriptor extendee =
+        final GenericDescriptor extendee =
           file.pool.lookupSymbol(proto.getExtendee(), this);
         if (!(extendee instanceof Descriptor)) {
           throw new DescriptorValidationException(this,
-            "\"" + proto.getExtendee() + "\" is not a message type.");
+              '\"' + proto.getExtendee() + "\" is not a message type.");
         }
-        this.containingType = (Descriptor)extendee;
+        containingType = (Descriptor)extendee;
 
         if (!getContainingType().isExtensionNumber(getNumber())) {
           throw new DescriptorValidationException(this,
-            "\"" + getContainingType().getFullName() + "\" does not declare " +
-            getNumber() + " as an extension number.");
+              '\"' + getContainingType().getFullName() +
+              "\" does not declare " + getNumber() +
+              " as an extension number.");
         }
       }
 
       if (proto.hasTypeName()) {
-        GenericDescriptor typeDescriptor =
+        final GenericDescriptor typeDescriptor =
           file.pool.lookupSymbol(proto.getTypeName(), this);
 
         if (!proto.hasType()) {
           // Choose field type based on symbol.
           if (typeDescriptor instanceof Descriptor) {
-            this.type = Type.MESSAGE;
+            type = Type.MESSAGE;
           } else if (typeDescriptor instanceof EnumDescriptor) {
-            this.type = Type.ENUM;
+            type = Type.ENUM;
           } else {
             throw new DescriptorValidationException(this,
-              "\"" + proto.getTypeName() + "\" is not a type.");
+                '\"' + proto.getTypeName() + "\" is not a type.");
           }
         }
 
         if (getJavaType() == JavaType.MESSAGE) {
           if (!(typeDescriptor instanceof Descriptor)) {
             throw new DescriptorValidationException(this,
-              "\"" + proto.getTypeName() + "\" is not a message type.");
+                '\"' + proto.getTypeName() + "\" is not a message type.");
           }
-          this.messageType = (Descriptor)typeDescriptor;
+          messageType = (Descriptor)typeDescriptor;
 
           if (proto.hasDefaultValue()) {
             throw new DescriptorValidationException(this,
@@ -941,9 +978,9 @@
         } else if (getJavaType() == JavaType.ENUM) {
           if (!(typeDescriptor instanceof EnumDescriptor)) {
             throw new DescriptorValidationException(this,
-              "\"" + proto.getTypeName() + "\" is not an enum type.");
+                '\"' + proto.getTypeName() + "\" is not an enum type.");
           }
-          this.enumType = (EnumDescriptor)typeDescriptor;
+          enumType = (EnumDescriptor)typeDescriptor;
         } else {
           throw new DescriptorValidationException(this,
             "Field with primitive type has type_name.");
@@ -972,20 +1009,18 @@
               defaultValue = TextFormat.parseInt32(proto.getDefaultValue());
               break;
             case UINT32:
-            case FIXED32: {
+            case FIXED32:
               defaultValue = TextFormat.parseUInt32(proto.getDefaultValue());
               break;
-            }
             case INT64:
             case SINT64:
             case SFIXED64:
               defaultValue = TextFormat.parseInt64(proto.getDefaultValue());
               break;
             case UINT64:
-            case FIXED64: {
+            case FIXED64:
               defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
               break;
-            }
             case FLOAT:
               defaultValue = Float.valueOf(proto.getDefaultValue());
               break;
@@ -1002,9 +1037,9 @@
               try {
                 defaultValue =
                   TextFormat.unescapeBytes(proto.getDefaultValue());
-              } catch (TextFormat.InvalidEscapeSequence e) {
+              } catch (TextFormat.InvalidEscapeSequenceException e) {
                 throw new DescriptorValidationException(this,
-                  "Couldn't parse default value: " + e.getMessage());
+                  "Couldn't parse default value: " + e.getMessage(), e);
               }
               break;
             case ENUM:
@@ -1012,7 +1047,7 @@
               if (defaultValue == null) {
                 throw new DescriptorValidationException(this,
                   "Unknown enum default value: \"" +
-                  proto.getDefaultValue() + "\"");
+                  proto.getDefaultValue() + '\"');
               }
               break;
             case MESSAGE:
@@ -1021,17 +1056,17 @@
                 "Message type had default value.");
           }
         } catch (NumberFormatException e) {
-          DescriptorValidationException validationException =
+          final DescriptorValidationException validationException =
             new DescriptorValidationException(this,
               "Could not parse default value: \"" +
-              proto.getDefaultValue() + "\"");
+              proto.getDefaultValue() + '\"');
           validationException.initCause(e);
           throw validationException;
         }
       } else {
         // Determine the default default for this field.
         if (isRepeated()) {
-          defaultValue = Collections.EMPTY_LIST;
+          defaultValue = Collections.emptyList();
         } else {
           switch (getJavaType()) {
             case ENUM:
@@ -1067,19 +1102,32 @@
       }
     }
 
-    /** See {@link FileDescriptor.setProto}. */
-    private void setProto(FieldDescriptorProto proto) {
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final FieldDescriptorProto proto) {
       this.proto = proto;
     }
+
+    /**
+     * For internal use only.  This is to satisfy the FieldDescriptorLite
+     * interface.
+     */
+    @Override
+    public MessageLite.Builder internalMergeFrom(
+        MessageLite.Builder to, MessageLite from) {
+      // FieldDescriptors are only used with non-lite messages so we can just
+      // down-cast and call mergeFrom directly.
+      return ((Message.Builder) to).mergeFrom((Message) from);
+    }
   }
 
   // =================================================================
 
   /** Describes an enum type. */
-  public static final class EnumDescriptor implements GenericDescriptor {
+  public static final class EnumDescriptor
+      implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> {
     /**
      * Get the index of this descriptor within its parent.
-     * @see Descriptors.Descriptor#getIndex()
+     * @see Descriptor#getIndex()
      */
     public int getIndex() { return index; }
 
@@ -1091,7 +1139,7 @@
 
     /**
      * Get the type's fully-qualified name.
-     * @see Descriptors.Descriptor#getFullName()
+     * @see Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1114,8 +1162,9 @@
      * @param name The unqualified name of the value (e.g. "FOO").
      * @return the value's decsriptor, or {@code null} if not found.
      */
-    public EnumValueDescriptor findValueByName(String name) {
-      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+    public EnumValueDescriptor findValueByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
       if (result != null && result instanceof EnumValueDescriptor) {
         return (EnumValueDescriptor)result;
       } else {
@@ -1129,7 +1178,7 @@
      * @param number The value's number.
      * @return the value's decsriptor, or {@code null} if not found.
      */
-    public EnumValueDescriptor findValueByNumber(int number) {
+    public EnumValueDescriptor findValueByNumber(final int number) {
       return file.pool.enumValuesByNumber.get(
         new DescriptorPool.DescriptorIntPair(this, number));
     }
@@ -1141,16 +1190,16 @@
     private final Descriptor containingType;
     private EnumValueDescriptor[] values;
 
-    private EnumDescriptor(EnumDescriptorProto proto,
-                           FileDescriptor file,
-                           Descriptor parent,
-                           int index)
+    private EnumDescriptor(final EnumDescriptorProto proto,
+                           final FileDescriptor file,
+                           final Descriptor parent,
+                           final int index)
                     throws DescriptorValidationException {
       this.index = index;
       this.proto = proto;
-      this.fullName = computeFullName(file, parent, proto.getName());
+      fullName = computeFullName(file, parent, proto.getName());
       this.file = file;
-      this.containingType = parent;
+      containingType = parent;
 
       if (proto.getValueCount() == 0) {
         // We cannot allow enums with no values because this would mean there
@@ -1161,15 +1210,15 @@
 
       values = new EnumValueDescriptor[proto.getValueCount()];
       for (int i = 0; i < proto.getValueCount(); i++) {
-        this.values[i] = new EnumValueDescriptor(
+        values[i] = new EnumValueDescriptor(
           proto.getValue(i), file, this, i);
       }
 
       file.pool.addSymbol(this);
     }
 
-    /** See {@link FileDescriptor.setProto}. */
-    private void setProto(EnumDescriptorProto proto) {
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final EnumDescriptorProto proto) {
       this.proto = proto;
 
       for (int i = 0; i < values.length; i++) {
@@ -1186,10 +1235,11 @@
    * with the same number after the first become aliases of the first.
    * However, they still have independent EnumValueDescriptors.
    */
-  public static final class EnumValueDescriptor implements GenericDescriptor {
+  public static final class EnumValueDescriptor
+      implements GenericDescriptor, Internal.EnumLite {
     /**
      * Get the index of this descriptor within its parent.
-     * @see Descriptors.Descriptor#getIndex()
+     * @see Descriptor#getIndex()
      */
     public int getIndex() { return index; }
 
@@ -1204,7 +1254,7 @@
 
     /**
      * Get the value's fully-qualified name.
-     * @see Descriptors.Descriptor#getFullName()
+     * @see Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1225,24 +1275,24 @@
     private final FileDescriptor file;
     private final EnumDescriptor type;
 
-    private EnumValueDescriptor(EnumValueDescriptorProto proto,
-                                FileDescriptor file,
-                                EnumDescriptor parent,
-                                int index)
+    private EnumValueDescriptor(final EnumValueDescriptorProto proto,
+                                final FileDescriptor file,
+                                final EnumDescriptor parent,
+                                final int index)
                          throws DescriptorValidationException {
       this.index = index;
       this.proto = proto;
       this.file = file;
-      this.type = parent;
+      type = parent;
 
-      this.fullName = parent.getFullName() + "." + proto.getName();
+      fullName = parent.getFullName() + '.' + proto.getName();
 
       file.pool.addSymbol(this);
       file.pool.addEnumValueByNumber(this);
     }
 
-    /** See {@link FileDescriptor.setProto}. */
-    private void setProto(EnumValueDescriptorProto proto) {
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final EnumValueDescriptorProto proto) {
       this.proto = proto;
     }
   }
@@ -1265,7 +1315,7 @@
 
     /**
      * Get the type's fully-qualified name.
-     * @see Descriptors.Descriptor#getFullName()
+     * @see Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1285,8 +1335,9 @@
      * @param name The unqualified name of the method (e.g. "Foo").
      * @return the method's decsriptor, or {@code null} if not found.
      */
-    public MethodDescriptor findMethodByName(String name) {
-      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+    public MethodDescriptor findMethodByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
       if (result != null && result instanceof MethodDescriptor) {
         return (MethodDescriptor)result;
       } else {
@@ -1300,18 +1351,18 @@
     private final FileDescriptor file;
     private MethodDescriptor[] methods;
 
-    private ServiceDescriptor(ServiceDescriptorProto proto,
-                              FileDescriptor file,
-                              int index)
+    private ServiceDescriptor(final ServiceDescriptorProto proto,
+                              final FileDescriptor file,
+                              final int index)
                        throws DescriptorValidationException {
       this.index = index;
       this.proto = proto;
-      this.fullName = computeFullName(file, null, proto.getName());
+      fullName = computeFullName(file, null, proto.getName());
       this.file = file;
 
-      this.methods = new MethodDescriptor[proto.getMethodCount()];
+      methods = new MethodDescriptor[proto.getMethodCount()];
       for (int i = 0; i < proto.getMethodCount(); i++) {
-        this.methods[i] = new MethodDescriptor(
+        methods[i] = new MethodDescriptor(
           proto.getMethod(i), file, this, i);
       }
 
@@ -1319,13 +1370,13 @@
     }
 
     private void crossLink() throws DescriptorValidationException {
-      for (int i = 0; i < methods.length; i++) {
-        methods[i].crossLink();
+      for (final MethodDescriptor method : methods) {
+        method.crossLink();
       }
     }
 
-    /** See {@link FileDescriptor.setProto}. */
-    private void setProto(ServiceDescriptorProto proto) {
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final ServiceDescriptorProto proto) {
       this.proto = proto;
 
       for (int i = 0; i < methods.length; i++) {
@@ -1354,7 +1405,7 @@
 
     /**
      * Get the method's fully-qualified name.
-     * @see Descriptors.Descriptor#getFullName()
+     * @see Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1385,54 +1436,54 @@
     private Descriptor inputType;
     private Descriptor outputType;
 
-    private MethodDescriptor(MethodDescriptorProto proto,
-                             FileDescriptor file,
-                             ServiceDescriptor parent,
-                             int index)
+    private MethodDescriptor(final MethodDescriptorProto proto,
+                             final FileDescriptor file,
+                             final ServiceDescriptor parent,
+                             final int index)
                       throws DescriptorValidationException {
       this.index = index;
       this.proto = proto;
       this.file = file;
-      this.service = parent;
+      service = parent;
 
-      this.fullName = parent.getFullName() + "." + proto.getName();
+      fullName = parent.getFullName() + '.' + proto.getName();
 
       file.pool.addSymbol(this);
     }
 
     private void crossLink() throws DescriptorValidationException {
-      GenericDescriptor inputType =
+      final GenericDescriptor input =
         file.pool.lookupSymbol(proto.getInputType(), this);
-      if (!(inputType instanceof Descriptor)) {
+      if (!(input instanceof Descriptor)) {
         throw new DescriptorValidationException(this,
-          "\"" + proto.getInputType() + "\" is not a message type.");
+            '\"' + proto.getInputType() + "\" is not a message type.");
       }
-      this.inputType = (Descriptor)inputType;
+      inputType = (Descriptor)input;
 
-      GenericDescriptor outputType =
+      final GenericDescriptor output =
         file.pool.lookupSymbol(proto.getOutputType(), this);
-      if (!(outputType instanceof Descriptor)) {
+      if (!(output instanceof Descriptor)) {
         throw new DescriptorValidationException(this,
-          "\"" + proto.getOutputType() + "\" is not a message type.");
+            '\"' + proto.getOutputType() + "\" is not a message type.");
       }
-      this.outputType = (Descriptor)outputType;
+      outputType = (Descriptor)output;
     }
 
-    /** See {@link FileDescriptor.setProto}. */
-    private void setProto(MethodDescriptorProto proto) {
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final MethodDescriptorProto proto) {
       this.proto = proto;
     }
   }
 
   // =================================================================
 
-  private static String computeFullName(FileDescriptor file,
-                                        Descriptor parent,
-                                        String name) {
+  private static String computeFullName(final FileDescriptor file,
+                                        final Descriptor parent,
+                                        final String name) {
     if (parent != null) {
-      return parent.getFullName() + "." + name;
+      return parent.getFullName() + '.' + name;
     } else if (file.getPackage().length() > 0) {
-      return file.getPackage() + "." + name;
+      return file.getPackage() + '.' + name;
     } else {
       return name;
     }
@@ -1444,7 +1495,7 @@
    * All descriptors except {@code FileDescriptor} implement this to make
    * {@code DescriptorPool}'s life easier.
    */
-  private static interface GenericDescriptor {
+  private interface GenericDescriptor {
     Message toProto();
     String getName();
     String getFullName();
@@ -1456,6 +1507,8 @@
    * are not valid.
    */
   public static class DescriptorValidationException extends Exception {
+    private static final long serialVersionUID = 5750205775490483148L;
+
     /** Gets the full name of the descriptor where the error occurred. */
     public String getProblemSymbolName() { return name; }
 
@@ -1473,27 +1526,36 @@
     private final Message proto;
     private final String description;
 
-    private DescriptorValidationException(GenericDescriptor problemDescriptor,
-                                          String description) {
-      super(problemDescriptor.getFullName() + ": " + description);
+    private DescriptorValidationException(
+        final GenericDescriptor problemDescriptor,
+        final String description) {
+      this(problemDescriptor, description, null);
+    }
+
+    private DescriptorValidationException(
+        final GenericDescriptor problemDescriptor,
+        final String description,
+        final Throwable cause) {
+      super(problemDescriptor.getFullName() + ": " + description, cause);
 
       // Note that problemDescriptor may be partially uninitialized, so we
       // don't want to expose it directly to the user.  So, we only provide
       // the name and the original proto.
-      this.name = problemDescriptor.getFullName();
-      this.proto = problemDescriptor.toProto();
+      name = problemDescriptor.getFullName();
+      proto = problemDescriptor.toProto();
       this.description = description;
     }
 
-    private DescriptorValidationException(FileDescriptor problemDescriptor,
-                                          String description) {
+    private DescriptorValidationException(
+        final FileDescriptor problemDescriptor,
+        final String description) {
       super(problemDescriptor.getName() + ": " + description);
 
       // Note that problemDescriptor may be partially uninitialized, so we
       // don't want to expose it directly to the user.  So, we only provide
       // the name and the original proto.
-      this.name = problemDescriptor.getName();
-      this.proto = problemDescriptor.toProto();
+      name = problemDescriptor.getName();
+      proto = problemDescriptor.toProto();
       this.description = description;
     }
   }
@@ -1505,16 +1567,16 @@
    * descriptors defined in a particular file.
    */
   private static final class DescriptorPool {
-    DescriptorPool(FileDescriptor[] dependencies) {
+    DescriptorPool(final FileDescriptor[] dependencies) {
       this.dependencies = new DescriptorPool[dependencies.length];
 
       for (int i = 0; i < dependencies.length; i++)  {
         this.dependencies[i] = dependencies[i].pool;
       }
 
-      for (int i = 0; i < dependencies.length; i++)  {
+      for (final FileDescriptor dependency : dependencies) {
         try {
-          addPackage(dependencies[i].getPackage(), dependencies[i]);
+          addPackage(dependency.getPackage(), dependency);
         } catch (DescriptorValidationException e) {
           // Can't happen, because addPackage() only fails when the name
           // conflicts with a non-package, but we have not yet added any
@@ -1524,23 +1586,27 @@
       }
     }
 
-    final DescriptorPool[] dependencies;
+    private final DescriptorPool[] dependencies;
 
-    final Map<String, GenericDescriptor> descriptorsByName =
+    private final Map<String, GenericDescriptor> descriptorsByName =
       new HashMap<String, GenericDescriptor>();
-    final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
+    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
       new HashMap<DescriptorIntPair, FieldDescriptor>();
-    final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
-      new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber
+        = new HashMap<DescriptorIntPair, EnumValueDescriptor>();
 
     /** Find a generic descriptor by fully-qualified name. */
-    GenericDescriptor findSymbol(String fullName) {
+    GenericDescriptor findSymbol(final String fullName) {
       GenericDescriptor result = descriptorsByName.get(fullName);
-      if (result != null) return result;
+      if (result != null) {
+        return result;
+      }
 
-      for (int i = 0; i < dependencies.length; i++) {
-        result = dependencies[i].descriptorsByName.get(fullName);
-        if (result != null) return result;
+      for (final DescriptorPool dependency : dependencies) {
+        result = dependency.descriptorsByName.get(fullName);
+        if (result != null) {
+          return result;
+        }
       }
 
       return null;
@@ -1552,8 +1618,8 @@
      * partially-qualified, or unqualified.  C++-like name lookup semantics
      * are used to search for the matching descriptor.
      */
-    GenericDescriptor lookupSymbol(String name,
-                                   GenericDescriptor relativeTo)
+    GenericDescriptor lookupSymbol(final String name,
+                                   final GenericDescriptor relativeTo)
                             throws DescriptorValidationException {
       // TODO(kenton):  This could be optimized in a number of ways.
 
@@ -1564,8 +1630,8 @@
       } else {
         // If "name" is a compound identifier, we want to search for the
         // first component of it, then search within it for the rest.
-        int firstPartLength = name.indexOf('.');
-        String firstPart;
+        final int firstPartLength = name.indexOf('.');
+        final String firstPart;
         if (firstPartLength == -1) {
           firstPart = name;
         } else {
@@ -1574,11 +1640,12 @@
 
         // We will search each parent scope of "relativeTo" looking for the
         // symbol.
-        StringBuilder scopeToTry = new StringBuilder(relativeTo.getFullName());
+        final StringBuilder scopeToTry =
+            new StringBuilder(relativeTo.getFullName());
 
         while (true) {
           // Chop off the last component of the scope.
-          int dotpos = scopeToTry.lastIndexOf(".");
+          final int dotpos = scopeToTry.lastIndexOf(".");
           if (dotpos == -1) {
             result = findSymbol(name);
             break;
@@ -1609,7 +1676,7 @@
 
       if (result == null) {
         throw new DescriptorValidationException(relativeTo,
-          "\"" + name + "\" is not defined.");
+            '\"' + name + "\" is not defined.");
       } else {
         return result;
       }
@@ -1619,30 +1686,30 @@
      * Adds a symbol to the symbol table.  If a symbol with the same name
      * already exists, throws an error.
      */
-    void addSymbol(GenericDescriptor descriptor)
+    void addSymbol(final GenericDescriptor descriptor)
             throws DescriptorValidationException {
       validateSymbolName(descriptor);
 
-      String fullName = descriptor.getFullName();
-      int dotpos = fullName.lastIndexOf('.');
+      final String fullName = descriptor.getFullName();
+      final int dotpos = fullName.lastIndexOf('.');
 
-      GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
+      final GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
       if (old != null) {
         descriptorsByName.put(fullName, old);
 
         if (descriptor.getFile() == old.getFile()) {
           if (dotpos == -1) {
             throw new DescriptorValidationException(descriptor,
-              "\"" + fullName + "\" is already defined.");
+                '\"' + fullName + "\" is already defined.");
           } else {
             throw new DescriptorValidationException(descriptor,
-              "\"" + fullName.substring(dotpos + 1) +
+                '\"' + fullName.substring(dotpos + 1) +
               "\" is already defined in \"" +
               fullName.substring(0, dotpos) + "\".");
           }
         } else {
           throw new DescriptorValidationException(descriptor,
-            "\"" + fullName + "\" is already defined in file \"" +
+              '\"' + fullName + "\" is already defined in file \"" +
             old.getFile().getName() + "\".");
         }
       }
@@ -1653,21 +1720,22 @@
      * just as placeholders so that someone cannot define, say, a message type
      * that has the same name as an existing package.
      */
-    static final class PackageDescriptor implements GenericDescriptor {
+    private static final class PackageDescriptor implements GenericDescriptor {
       public Message toProto()        { return file.toProto(); }
       public String getName()         { return name;           }
       public String getFullName()     { return fullName;       }
       public FileDescriptor getFile() { return file;           }
 
-      PackageDescriptor(String name, String fullName, FileDescriptor file) {
+      PackageDescriptor(final String name, final String fullName,
+                        final FileDescriptor file) {
         this.file = file;
         this.fullName = fullName;
         this.name = name;
       }
 
-      String name;
-      String fullName;
-      FileDescriptor file;
+      private final String name;
+      private final String fullName;
+      private final FileDescriptor file;
     }
 
     /**
@@ -1676,46 +1744,50 @@
      * under the same name, an exception is thrown.  If the package has
      * multiple components, this also adds the parent package(s).
      */
-    void addPackage(String fullName, FileDescriptor file)
+    void addPackage(final String fullName, final FileDescriptor file)
              throws DescriptorValidationException {
-      int dotpos = fullName.lastIndexOf('.');
-      String name;
-      if (dotpos != -1) {
+      final int dotpos = fullName.lastIndexOf('.');
+      final String name;
+      if (dotpos == -1) {
+        name = fullName;
+      } else {
         addPackage(fullName.substring(0, dotpos), file);
         name = fullName.substring(dotpos + 1);
-      } else {
-        name = fullName;
       }
 
-      GenericDescriptor old =
+      final GenericDescriptor old =
         descriptorsByName.put(fullName,
           new PackageDescriptor(name, fullName, file));
       if (old != null) {
         descriptorsByName.put(fullName, old);
         if (!(old instanceof PackageDescriptor)) {
           throw new DescriptorValidationException(file,
-            "\"" + name + "\" is already defined (as something other than a " +
-            "package) in file \"" + old.getFile().getName() + "\".");
+              '\"' + name + "\" is already defined (as something other than a "
+              + "package) in file \"" + old.getFile().getName() + "\".");
         }
       }
     }
 
     /** A (GenericDescriptor, int) pair, used as a map key. */
-    static final class DescriptorIntPair {
-      final GenericDescriptor descriptor;
-      final int number;
+    private static final class DescriptorIntPair {
+      private final GenericDescriptor descriptor;
+      private final int number;
 
-      DescriptorIntPair(GenericDescriptor descriptor, int number) {
+      DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
         this.descriptor = descriptor;
         this.number = number;
       }
 
+      @Override
       public int hashCode() {
         return descriptor.hashCode() * ((1 << 16) - 1) + number;
       }
-      public boolean equals(Object obj) {
-        if (!(obj instanceof DescriptorIntPair)) return false;
-        DescriptorIntPair other = (DescriptorIntPair)obj;
+      @Override
+      public boolean equals(final Object obj) {
+        if (!(obj instanceof DescriptorIntPair)) {
+          return false;
+        }
+        final DescriptorIntPair other = (DescriptorIntPair)obj;
         return descriptor == other.descriptor && number == other.number;
       }
     }
@@ -1724,11 +1796,11 @@
      * Adds a field to the fieldsByNumber table.  Throws an exception if a
      * field with hte same containing type and number already exists.
      */
-    void addFieldByNumber(FieldDescriptor field)
+    void addFieldByNumber(final FieldDescriptor field)
                    throws DescriptorValidationException {
-      DescriptorIntPair key =
+      final DescriptorIntPair key =
         new DescriptorIntPair(field.getContainingType(), field.getNumber());
-      FieldDescriptor old = fieldsByNumber.put(key, field);
+      final FieldDescriptor old = fieldsByNumber.put(key, field);
       if (old != null) {
         fieldsByNumber.put(key, old);
         throw new DescriptorValidationException(field,
@@ -1744,10 +1816,10 @@
      * with the same type and number already exists, does nothing.  (This is
      * allowed; the first value define with the number takes precedence.)
      */
-    void addEnumValueByNumber(EnumValueDescriptor value) {
-      DescriptorIntPair key =
+    void addEnumValueByNumber(final EnumValueDescriptor value) {
+      final DescriptorIntPair key =
         new DescriptorIntPair(value.getType(), value.getNumber());
-      EnumValueDescriptor old = enumValuesByNumber.put(key, value);
+      final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
       if (old != null) {
         enumValuesByNumber.put(key, old);
         // Not an error:  Multiple enum values may have the same number, but
@@ -1759,15 +1831,15 @@
      * Verifies that the descriptor's name is valid (i.e. it contains only
      * letters, digits, and underscores, and does not start with a digit).
      */
-    void validateSymbolName(GenericDescriptor descriptor)
-                     throws DescriptorValidationException {
-      String name = descriptor.getName();
+    static void validateSymbolName(final GenericDescriptor descriptor)
+                                   throws DescriptorValidationException {
+      final String name = descriptor.getName();
       if (name.length() == 0) {
         throw new DescriptorValidationException(descriptor, "Missing name.");
       } else {
         boolean valid = true;
         for (int i = 0; i < name.length(); i++) {
-          char c = name.charAt(i);
+          final char c = name.charAt(i);
           // Non-ASCII characters are not valid in protobuf identifiers, even
           // if they are letters or digits.
           if (c >= 128) {
@@ -1784,7 +1856,7 @@
         }
         if (!valid) {
           throw new DescriptorValidationException(descriptor,
-            "\"" + name + "\" is not a valid identifier.");
+              '\"' + name + "\" is not a valid identifier.");
         }
       }
     }
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index 59fb7b0..c106b66 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -45,14 +45,14 @@
  */
 public final class DynamicMessage extends AbstractMessage {
   private final Descriptor type;
-  private final FieldSet fields;
+  private final FieldSet<FieldDescriptor> fields;
   private final UnknownFieldSet unknownFields;
   private int memoizedSize = -1;
 
   /**
    * Construct a {@code DynamicMessage} using the given {@code FieldSet}.
    */
-  private DynamicMessage(Descriptor type, FieldSet fields,
+  private DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
                          UnknownFieldSet unknownFields) {
     this.type = type;
     this.fields = fields;
@@ -64,7 +64,7 @@
    * given type.
    */
   public static DynamicMessage getDefaultInstance(Descriptor type) {
-    return new DynamicMessage(type, FieldSet.emptySet(),
+    return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
                               UnknownFieldSet.getDefaultInstance());
   }
 
@@ -160,7 +160,11 @@
     verifyContainingType(field);
     Object result = fields.getField(field);
     if (result == null) {
-      result = getDefaultInstance(field.getMessageType());
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        result = getDefaultInstance(field.getMessageType());
+      } else {
+        result = field.getDefaultValue();
+      }
     }
     return result;
   }
@@ -179,15 +183,31 @@
     return unknownFields;
   }
 
+  private static boolean isInitialized(Descriptor type,
+                                       FieldSet<FieldDescriptor> fields) {
+    // Check that all required fields are present.
+    for (final FieldDescriptor field : type.getFields()) {
+      if (field.isRequired()) {
+        if (!fields.hasField(field)) {
+          return false;
+        }
+      }
+    }
+
+    // Check that embedded messages are initialized.
+    return fields.isInitialized();
+  }
+
   public boolean isInitialized() {
-    return fields.isInitialized(type);
+    return isInitialized(type, fields);
   }
 
   public void writeTo(CodedOutputStream output) throws IOException {
-    fields.writeTo(output);
     if (type.getOptions().getMessageSetWireFormat()) {
+      fields.writeMessageSetTo(output);
       unknownFields.writeAsMessageSetTo(output);
     } else {
+      fields.writeTo(output);
       unknownFields.writeTo(output);
     }
   }
@@ -196,10 +216,11 @@
     int size = memoizedSize;
     if (size != -1) return size;
 
-    size = fields.getSerializedSize();
     if (type.getOptions().getMessageSetWireFormat()) {
+      size = fields.getMessageSetSerializedSize();
       size += unknownFields.getSerializedSizeAsMessageSet();
     } else {
+      size = fields.getSerializedSize();
       size += unknownFields.getSerializedSize();
     }
 
@@ -230,7 +251,7 @@
    */
   public static final class Builder extends AbstractMessage.Builder<Builder> {
     private final Descriptor type;
-    private FieldSet fields;
+    private FieldSet<FieldDescriptor> fields;
     private UnknownFieldSet unknownFields;
 
     /** Construct a {@code Builder} for the given type. */
@@ -244,25 +265,33 @@
     // Implementation of Message.Builder interface.
 
     public Builder clear() {
+      if (fields == null) {
+        throw new IllegalStateException("Cannot call clear() after build().");
+      }
       fields.clear();
       return this;
     }
 
     public Builder mergeFrom(Message other) {
-      if (other.getDescriptorForType() != type) {
-        throw new IllegalArgumentException(
-          "mergeFrom(Message) can only merge messages of the same type.");
+      if (other instanceof DynamicMessage) {
+        // This should be somewhat faster than calling super.mergeFrom().
+        DynamicMessage otherDynamicMessage = (DynamicMessage) other;
+        if (otherDynamicMessage.type != type) {
+          throw new IllegalArgumentException(
+            "mergeFrom(Message) can only merge messages of the same type.");
+        }
+        fields.mergeFrom(otherDynamicMessage.fields);
+        mergeUnknownFields(otherDynamicMessage.unknownFields);
+        return this;
+      } else {
+        return super.mergeFrom(other);
       }
-
-      fields.mergeFrom(other);
-      mergeUnknownFields(other.getUnknownFields());
-      return this;
     }
 
     public DynamicMessage build() {
       // If fields == null, we'll throw an appropriate exception later.
       if (fields != null && !isInitialized()) {
-        throw new UninitializedMessageException(
+        throw newUninitializedMessageException(
           new DynamicMessage(type, fields, unknownFields));
       }
       return buildPartial();
@@ -275,7 +304,7 @@
      */
     private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
       if (!isInitialized()) {
-        throw new UninitializedMessageException(
+        throw newUninitializedMessageException(
             new DynamicMessage(type, fields, unknownFields))
           .asInvalidProtocolBufferException();
       }
@@ -302,17 +331,7 @@
     }
 
     public boolean isInitialized() {
-      return fields.isInitialized(type);
-    }
-
-    public Builder mergeFrom(CodedInputStream input,
-                             ExtensionRegistry extensionRegistry)
-                             throws IOException {
-      UnknownFieldSet.Builder unknownFieldsBuilder =
-        UnknownFieldSet.newBuilder(unknownFields);
-      fields.mergeFrom(input, unknownFieldsBuilder, extensionRegistry, this);
-      unknownFields = unknownFieldsBuilder.build();
-      return this;
+      return DynamicMessage.isInitialized(type, fields);
     }
 
     public Descriptor getDescriptorForType() {
@@ -347,7 +366,11 @@
       verifyContainingType(field);
       Object result = fields.getField(field);
       if (result == null) {
-        result = getDefaultInstance(field.getMessageType());
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          result = getDefaultInstance(field.getMessageType());
+        } else {
+          result = field.getDefaultValue();
+        }
       }
       return result;
     }
diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
index 45396f6..87bbd6e 100644
--- a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
+++ b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -84,18 +84,16 @@
  * would be slow.  Second, corrupt data would not be detected until first
  * access, at which point it would be much harder to deal with it.  Third, it
  * could violate the expectation that message objects are immutable, since the
- * type provided could be any arbitrary message class.  An unpriviledged user
+ * type provided could be any arbitrary message class.  An unprivileged user
  * could take advantage of this to inject a mutable object into a message
- * belonging to priviledged code and create mischief.
+ * belonging to privileged code and create mischief.
  *
  * @author kenton@google.com Kenton Varda
  */
-public final class ExtensionRegistry {
+public final class ExtensionRegistry extends ExtensionRegistryLite {
   /** Construct a new, empty instance. */
   public static ExtensionRegistry newInstance() {
-    return new ExtensionRegistry(
-      new HashMap<String, ExtensionInfo>(),
-      new HashMap<DescriptorIntPair, ExtensionInfo>());
+    return new ExtensionRegistry();
   }
 
   /** Get the unmodifiable singleton empty instance. */
@@ -104,10 +102,9 @@
   }
 
   /** Returns an unmodifiable view of the registry. */
+  @Override
   public ExtensionRegistry getUnmodifiable() {
-    return new ExtensionRegistry(
-      Collections.unmodifiableMap(extensionsByName),
-      Collections.unmodifiableMap(extensionsByNumber));
+    return new ExtensionRegistry(this);
   }
 
   /** A (Descriptor, Message) pair, returned by lookup methods. */
@@ -121,11 +118,12 @@
      */
     public final Message defaultInstance;
 
-    private ExtensionInfo(FieldDescriptor descriptor) {
+    private ExtensionInfo(final FieldDescriptor descriptor) {
       this.descriptor = descriptor;
-      this.defaultInstance = null;
+      defaultInstance = null;
     }
-    private ExtensionInfo(FieldDescriptor descriptor, Message defaultInstance) {
+    private ExtensionInfo(final FieldDescriptor descriptor,
+                          final Message defaultInstance) {
       this.descriptor = descriptor;
       this.defaultInstance = defaultInstance;
     }
@@ -139,7 +137,7 @@
    * @return Information about the extension if found, or {@code null}
    *         otherwise.
    */
-  public ExtensionInfo findExtensionByName(String fullName) {
+  public ExtensionInfo findExtensionByName(final String fullName) {
     return extensionsByName.get(fullName);
   }
 
@@ -149,14 +147,14 @@
    * @return Information about the extension if found, or {@code null}
    *         otherwise.
    */
-  public ExtensionInfo findExtensionByNumber(Descriptor containingType,
-                                             int fieldNumber) {
+  public ExtensionInfo findExtensionByNumber(final Descriptor containingType,
+                                             final int fieldNumber) {
     return extensionsByNumber.get(
       new DescriptorIntPair(containingType, fieldNumber));
   }
 
   /** Add an extension from a generated file to the registry. */
-  public void add(GeneratedMessage.GeneratedExtension<?, ?> extension) {
+  public void add(final GeneratedMessage.GeneratedExtension<?, ?> extension) {
     if (extension.getDescriptor().getJavaType() ==
         FieldDescriptor.JavaType.MESSAGE) {
       add(new ExtensionInfo(extension.getDescriptor(),
@@ -167,7 +165,7 @@
   }
 
   /** Add a non-message-type extension to the registry by descriptor. */
-  public void add(FieldDescriptor type) {
+  public void add(final FieldDescriptor type) {
     if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
       throw new IllegalArgumentException(
         "ExtensionRegistry.add() must be provided a default instance when " +
@@ -177,7 +175,7 @@
   }
 
   /** Add a message-type extension to the registry by descriptor. */
-  public void add(FieldDescriptor type, Message defaultInstance) {
+  public void add(final FieldDescriptor type, final Message defaultInstance) {
     if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
       throw new IllegalArgumentException(
         "ExtensionRegistry.add() provided a default instance for a " +
@@ -189,22 +187,30 @@
   // =================================================================
   // Private stuff.
 
-  private ExtensionRegistry(
-      Map<String, ExtensionInfo> extensionsByName,
-      Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber) {
-    this.extensionsByName = extensionsByName;
-    this.extensionsByNumber = extensionsByNumber;
+  private ExtensionRegistry() {
+    this.extensionsByName = new HashMap<String, ExtensionInfo>();
+    this.extensionsByNumber = new HashMap<DescriptorIntPair, ExtensionInfo>();
+  }
+
+  private ExtensionRegistry(ExtensionRegistry other) {
+    super(other);
+    this.extensionsByName = Collections.unmodifiableMap(other.extensionsByName);
+    this.extensionsByNumber =
+        Collections.unmodifiableMap(other.extensionsByNumber);
   }
 
   private final Map<String, ExtensionInfo> extensionsByName;
   private final Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
 
-  private static final ExtensionRegistry EMPTY =
-    new ExtensionRegistry(
-      Collections.<String, ExtensionInfo>emptyMap(),
-      Collections.<DescriptorIntPair, ExtensionInfo>emptyMap());
+  private ExtensionRegistry(boolean empty) {
+    super(ExtensionRegistryLite.getEmptyRegistry());
+    this.extensionsByName = Collections.<String, ExtensionInfo>emptyMap();
+    this.extensionsByNumber =
+        Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+  }
+  private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true);
 
-  private void add(ExtensionInfo extension) {
+  private void add(final ExtensionInfo extension) {
     if (!extension.descriptor.isExtension()) {
       throw new IllegalArgumentException(
         "ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
@@ -217,7 +223,7 @@
                             extension.descriptor.getNumber()),
       extension);
 
-    FieldDescriptor field = extension.descriptor;
+    final FieldDescriptor field = extension.descriptor;
     if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
         field.getType() == FieldDescriptor.Type.MESSAGE &&
         field.isOptional() &&
@@ -231,20 +237,24 @@
 
   /** A (GenericDescriptor, int) pair, used as a map key. */
   private static final class DescriptorIntPair {
-    final Descriptor descriptor;
-    final int number;
+    private final Descriptor descriptor;
+    private final int number;
 
-    DescriptorIntPair(Descriptor descriptor, int number) {
+    DescriptorIntPair(final Descriptor descriptor, final int number) {
       this.descriptor = descriptor;
       this.number = number;
     }
 
+    @Override
     public int hashCode() {
       return descriptor.hashCode() * ((1 << 16) - 1) + number;
     }
-    public boolean equals(Object obj) {
-      if (!(obj instanceof DescriptorIntPair)) return false;
-      DescriptorIntPair other = (DescriptorIntPair)obj;
+    @Override
+    public boolean equals(final Object obj) {
+      if (!(obj instanceof DescriptorIntPair)) {
+        return false;
+      }
+      final DescriptorIntPair other = (DescriptorIntPair)obj;
       return descriptor == other.descriptor && number == other.number;
     }
   }
diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
new file mode 100644
index 0000000..d5288dd
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -0,0 +1,169 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Equivalent to {@link ExtensionRegistry} but supports only "lite" types.
+ * <p>
+ * If all of your types are lite types, then you only need to use
+ * {@code ExtensionRegistryLite}.  Similarly, if all your types are regular
+ * types, then you only need {@link ExtensionRegistry}.  Typically it does not
+ * make sense to mix the two, since if you have any regular types in your
+ * program, you then require the full runtime and lose all the benefits of
+ * the lite runtime, so you might as well make all your types be regular types.
+ * However, in some cases (e.g. when depending on multiple third-patry libraries
+ * where one uses lite types and one uses regular), you may find yourself
+ * wanting to mix the two.  In this case things get more complicated.
+ * <p>
+ * There are three factors to consider:  Whether the type being extended is
+ * lite, whether the embedded type (in the case of a message-typed extension)
+ * is lite, and whether the extension itself is lite.  Since all three are
+ * declared in different files, they could all be different.  Here are all
+ * the combinations and which type of registry to use:
+ * <pre>
+ *   Extended type     Inner type    Extension         Use registry
+ *   =======================================================================
+ *   lite              lite          lite              ExtensionRegistryLite
+ *   lite              regular       lite              ExtensionRegistry
+ *   regular           regular       regular           ExtensionRegistry
+ *   all other combinations                            not supported
+ * </pre>
+ * <p>
+ * Note that just as regular types are not allowed to contain lite-type fields,
+ * they are also not allowed to contain lite-type extensions.  This is because
+ * regular types must be fully accessible via reflection, which in turn means
+ * that all the inner messages must also support reflection.  On the other hand,
+ * since regular types implement the entire lite interface, there is no problem
+ * with embedding regular types inside lite types.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ExtensionRegistryLite {
+  /** Construct a new, empty instance. */
+  public static ExtensionRegistryLite newInstance() {
+    return new ExtensionRegistryLite();
+  }
+
+  /** Get the unmodifiable singleton empty instance. */
+  public static ExtensionRegistryLite getEmptyRegistry() {
+    return EMPTY;
+  }
+
+  /** Returns an unmodifiable view of the registry. */
+  public ExtensionRegistryLite getUnmodifiable() {
+    return new ExtensionRegistryLite(this);
+  }
+
+  /**
+   * Find an extension by containing type and field number.
+   *
+   * @return Information about the extension if found, or {@code null}
+   *         otherwise.
+   */
+  @SuppressWarnings("unchecked")
+  public <ContainingType extends MessageLite>
+      GeneratedMessageLite.GeneratedExtension<ContainingType, ?>
+        findLiteExtensionByNumber(
+          final ContainingType containingTypeDefaultInstance,
+          final int fieldNumber) {
+    return (GeneratedMessageLite.GeneratedExtension<ContainingType, ?>)
+      extensionsByNumber.get(
+        new ObjectIntPair(containingTypeDefaultInstance, fieldNumber));
+  }
+
+  /** Add an extension from a lite generated file to the registry. */
+  public final void add(
+      final GeneratedMessageLite.GeneratedExtension<?, ?> extension) {
+    extensionsByNumber.put(
+      new ObjectIntPair(extension.getContainingTypeDefaultInstance(),
+                        extension.getNumber()),
+      extension);
+  }
+
+  // =================================================================
+  // Private stuff.
+
+  // Constructors are package-private so that ExtensionRegistry can subclass
+  // this.
+
+  ExtensionRegistryLite() {
+    this.extensionsByNumber =
+        new HashMap<ObjectIntPair,
+                    GeneratedMessageLite.GeneratedExtension<?, ?>>();
+  }
+
+  ExtensionRegistryLite(ExtensionRegistryLite other) {
+    if (other == EMPTY) {
+      this.extensionsByNumber = Collections.emptyMap();
+    } else {
+      this.extensionsByNumber =
+        Collections.unmodifiableMap(other.extensionsByNumber);
+    }
+  }
+
+  private final Map<ObjectIntPair,
+                    GeneratedMessageLite.GeneratedExtension<?, ?>>
+      extensionsByNumber;
+
+  private ExtensionRegistryLite(boolean empty) {
+    this.extensionsByNumber = Collections.emptyMap();
+  }
+  private static final ExtensionRegistryLite EMPTY =
+    new ExtensionRegistryLite(true);
+
+  /** A (Object, int) pair, used as a map key. */
+  private static final class ObjectIntPair {
+    private final Object object;
+    private final int number;
+
+    ObjectIntPair(final Object object, final int number) {
+      this.object = object;
+      this.number = number;
+    }
+
+    @Override
+    public int hashCode() {
+      return System.identityHashCode(object) * ((1 << 16) - 1) + number;
+    }
+    @Override
+    public boolean equals(final Object obj) {
+      if (!(obj instanceof ObjectIntPair)) {
+        return false;
+      }
+      final ObjectIntPair other = (ObjectIntPair)obj;
+      return object == other.object && number == other.number;
+    }
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index 01da3fa..93e55f2 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -30,16 +30,13 @@
 
 package com.google.protobuf;
 
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.Descriptors.EnumValueDescriptor;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
+import java.io.IOException;
 
 /**
  * A class which represents an arbitrary set of fields of some message type.
@@ -49,43 +46,70 @@
  *
  * @author kenton@google.com Kenton Varda
  */
-final class FieldSet {
-  private Map<FieldDescriptor, Object> fields;
+final class FieldSet<FieldDescriptorType extends
+      FieldSet.FieldDescriptorLite<FieldDescriptorType>> {
+  /**
+   * Interface for a FieldDescriptor or lite extension descriptor.  This
+   * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}.
+   */
+  public interface FieldDescriptorLite<T extends FieldDescriptorLite<T>>
+      extends Comparable<T> {
+    int getNumber();
+    WireFormat.FieldType getLiteType();
+    WireFormat.JavaType getLiteJavaType();
+    boolean isRepeated();
+    boolean isPacked();
+    Internal.EnumLiteMap<?> getEnumType();
+
+    // If getLiteJavaType() == MESSAGE, this merges a message object of the
+    // type into a builder of the type.  Returns {@code to}.
+    MessageLite.Builder internalMergeFrom(
+        MessageLite.Builder to, MessageLite from);
+  }
+
+  private Map<FieldDescriptorType, Object> fields;
 
   /** Construct a new FieldSet. */
   private FieldSet() {
     // Use a TreeMap because fields need to be in canonical order when
     // serializing.
-    this.fields = new TreeMap<FieldDescriptor, Object>();
+    // TODO(kenton):  Maybe use some sort of sparse array instead?  It would
+    //   even make sense to store the first 16 or so tags in a flat array
+    //   to make DynamicMessage faster.
+    fields = new TreeMap<FieldDescriptorType, Object>();
   }
 
   /**
-   * Construct a new FieldSet with the given map.  This is only used by
-   * DEFAULT_INSTANCE, to pass in an immutable empty map.
+   * Construct an empty FieldSet.  This is only used to initialize
+   * DEFAULT_INSTANCE.
    */
-  private FieldSet(Map<FieldDescriptor, Object> fields) {
-    this.fields = fields;
+  private FieldSet(final boolean dummy) {
+    this.fields = Collections.emptyMap();
   }
 
   /** Construct a new FieldSet. */
-  public static FieldSet newFieldSet() {
-    return new FieldSet();
+  public static <T extends FieldSet.FieldDescriptorLite<T>>
+      FieldSet<T> newFieldSet() {
+    return new FieldSet<T>();
   }
 
   /** Get an immutable empty FieldSet. */
-  public static FieldSet emptySet() {
+  @SuppressWarnings("unchecked")
+  public static <T extends FieldSet.FieldDescriptorLite<T>>
+      FieldSet<T> emptySet() {
     return DEFAULT_INSTANCE;
   }
-  private static final FieldSet DEFAULT_INSTANCE =
-    new FieldSet(Collections.<FieldDescriptor, Object>emptyMap());
+  @SuppressWarnings("unchecked")
+  private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
 
   /** Make this FieldSet immutable from this point forward. */
   @SuppressWarnings("unchecked")
   public void makeImmutable() {
-    for (Map.Entry<FieldDescriptor, Object> entry: fields.entrySet()) {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
       if (entry.getKey().isRepeated()) {
-        List value = (List)entry.getValue();
-        entry.setValue(Collections.unmodifiableList(value));
+        final List value = (List)entry.getValue();
+        fields.put(entry.getKey(), Collections.unmodifiableList(value));
       }
     }
     fields = Collections.unmodifiableMap(fields);
@@ -98,56 +122,52 @@
     fields.clear();
   }
 
-  /** See {@link Message#getAllFields()}. */
-  public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+  /**
+   * Get a simple map containing all the fields.
+   */
+  public Map<FieldDescriptorType, Object> getAllFields() {
     return Collections.unmodifiableMap(fields);
   }
 
   /**
-   * Get an interator to the field map.  This iterator should not be leaked
+   * Get an iterator to the field map.  This iterator should not be leaked
    * out of the protobuf library as it is not protected from mutation.
    */
-  public Iterator<Map.Entry<Descriptors.FieldDescriptor, Object>> iterator() {
+  public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
     return fields.entrySet().iterator();
   }
 
-  /** See {@link Message#hasField(Descriptors.FieldDescriptor)}. */
-  public boolean hasField(Descriptors.FieldDescriptor field) {
-    if (field.isRepeated()) {
+  /**
+   * Useful for implementing
+   * {@link Message#hasField(Descriptors.FieldDescriptor)}.
+   */
+  public boolean hasField(final FieldDescriptorType descriptor) {
+    if (descriptor.isRepeated()) {
       throw new IllegalArgumentException(
         "hasField() can only be called on non-repeated fields.");
     }
 
-    return fields.containsKey(field);
+    return fields.get(descriptor) != null;
   }
 
   /**
-   * See {@link Message#getField(Descriptors.FieldDescriptor)}.  This method
-   * returns {@code null} if the field is a singular message type and is not
-   * set; in this case it is up to the caller to fetch the message's default
-   * instance.
+   * Useful for implementing
+   * {@link Message#getField(Descriptors.FieldDescriptor)}.  This method
+   * returns {@code null} if the field is not set; in this case it is up
+   * to the caller to fetch the field's default value.
    */
-  public Object getField(Descriptors.FieldDescriptor field) {
-    Object result = fields.get(field);
-    if (result == null) {
-      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        if (field.isRepeated()) {
-          return Collections.emptyList();
-        } else {
-          return null;
-        }
-      } else {
-        return field.getDefaultValue();
-      }
-    } else {
-      return result;
-    }
+  public Object getField(final FieldDescriptorType descriptor) {
+    return fields.get(descriptor);
   }
 
-  /** See {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
+   */
   @SuppressWarnings("unchecked")
-  public void setField(Descriptors.FieldDescriptor field, Object value) {
-    if (field.isRepeated()) {
+  public void setField(final FieldDescriptorType descriptor,
+                       Object value) {
+    if (descriptor.isRepeated()) {
       if (!(value instanceof List)) {
         throw new IllegalArgumentException(
           "Wrong object type used with protocol message reflection.");
@@ -155,78 +175,108 @@
 
       // Wrap the contents in a new list so that the caller cannot change
       // the list's contents after setting it.
-      List newList = new ArrayList();
+      final List newList = new ArrayList();
       newList.addAll((List)value);
-      for (Object element : newList) {
-        verifyType(field, element);
+      for (final Object element : newList) {
+        verifyType(descriptor.getLiteType(), element);
       }
       value = newList;
     } else {
-      verifyType(field, value);
+      verifyType(descriptor.getLiteType(), value);
     }
 
-    fields.put(field, value);
+    fields.put(descriptor, value);
   }
 
-  /** See {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */
-  public void clearField(Descriptors.FieldDescriptor field) {
-    fields.remove(field);
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}.
+   */
+  public void clearField(final FieldDescriptorType descriptor) {
+    fields.remove(descriptor);
   }
 
-  /** See {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. */
-  public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
-    if (!field.isRepeated()) {
-      throw new IllegalArgumentException(
-        "getRepeatedFieldCount() can only be called on repeated fields.");
-    }
-
-    return ((List)getField(field)).size();
-  }
-
-  /** See {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */
-  public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
-    if (!field.isRepeated()) {
+  /**
+   * Useful for implementing
+   * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}.
+   */
+  public int getRepeatedFieldCount(final FieldDescriptorType descriptor) {
+    if (!descriptor.isRepeated()) {
       throw new IllegalArgumentException(
         "getRepeatedField() can only be called on repeated fields.");
     }
 
-    return ((List)getField(field)).get(index);
+    final Object value = fields.get(descriptor);
+    if (value == null) {
+      return 0;
+    } else {
+      return ((List) value).size();
+    }
   }
 
-  /** See {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. */
-  @SuppressWarnings("unchecked")
-  public void setRepeatedField(Descriptors.FieldDescriptor field, int index,
-                               Object value) {
-    if (!field.isRepeated()) {
+  /**
+   * Useful for implementing
+   * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}.
+   */
+  public Object getRepeatedField(final FieldDescriptorType descriptor,
+                                 final int index) {
+    if (!descriptor.isRepeated()) {
       throw new IllegalArgumentException(
-        "setRepeatedField() can only be called on repeated fields.");
+        "getRepeatedField() can only be called on repeated fields.");
     }
 
-    verifyType(field, value);
+    final Object value = fields.get(descriptor);
 
-    List list = (List)fields.get(field);
+    if (value == null) {
+      throw new IndexOutOfBoundsException();
+    } else {
+      return ((List) value).get(index);
+    }
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}.
+   */
+  @SuppressWarnings("unchecked")
+  public void setRepeatedField(final FieldDescriptorType descriptor,
+                               final int index,
+                               final Object value) {
+    if (!descriptor.isRepeated()) {
+      throw new IllegalArgumentException(
+        "getRepeatedField() can only be called on repeated fields.");
+    }
+
+    final Object list = fields.get(descriptor);
     if (list == null) {
       throw new IndexOutOfBoundsException();
     }
 
-    list.set(index, value);
+    verifyType(descriptor.getLiteType(), value);
+    ((List) list).set(index, value);
   }
 
-  /** See {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. */
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}.
+   */
   @SuppressWarnings("unchecked")
-  public void addRepeatedField(Descriptors.FieldDescriptor field,
-                               Object value) {
-    if (!field.isRepeated()) {
+  public void addRepeatedField(final FieldDescriptorType descriptor,
+                               final Object value) {
+    if (!descriptor.isRepeated()) {
       throw new IllegalArgumentException(
-        "setRepeatedField() can only be called on repeated fields.");
+        "addRepeatedField() can only be called on repeated fields.");
     }
 
-    verifyType(field, value);
+    verifyType(descriptor.getLiteType(), value);
 
-    List list = (List)fields.get(field);
-    if (list == null) {
+    final Object existingValue = fields.get(descriptor);
+    List list;
+    if (existingValue == null) {
       list = new ArrayList();
-      fields.put(field, list);
+      fields.put(descriptor, list);
+    } else {
+      list = (List) existingValue;
     }
 
     list.add(value);
@@ -239,9 +289,14 @@
    *
    * @throws IllegalArgumentException The value is not of the right type.
    */
-  private void verifyType(FieldDescriptor field, Object value) {
+  private static void verifyType(final WireFormat.FieldType type,
+                                 final Object value) {
+    if (value == null) {
+      throw new NullPointerException();
+    }
+
     boolean isValid = false;
-    switch (field.getJavaType()) {
+    switch (type.getJavaType()) {
       case INT:          isValid = value instanceof Integer   ; break;
       case LONG:         isValid = value instanceof Long      ; break;
       case FLOAT:        isValid = value instanceof Float     ; break;
@@ -250,26 +305,25 @@
       case STRING:       isValid = value instanceof String    ; break;
       case BYTE_STRING:  isValid = value instanceof ByteString; break;
       case ENUM:
-        isValid = value instanceof EnumValueDescriptor &&
-          ((EnumValueDescriptor)value).getType() == field.getEnumType();
+        // TODO(kenton):  Caller must do type checking here, I guess.
+        isValid = value instanceof Internal.EnumLite;
         break;
       case MESSAGE:
-        isValid = value instanceof Message &&
-          ((Message)value).getDescriptorForType() == field.getMessageType();
+        // TODO(kenton):  Caller must do type checking here, I guess.
+        isValid = value instanceof MessageLite;
         break;
     }
 
     if (!isValid) {
-      // When chaining calls to setField(), it can be hard to tell from
-      // the stack trace which exact call failed, since the whole chain is
-      // considered one line of code.  So, let's make sure to include the
-      // field name and other useful info in the exception.
+      // TODO(kenton):  When chaining calls to setField(), it can be hard to
+      //   tell from the stack trace which exact call failed, since the whole
+      //   chain is considered one line of code.  It would be nice to print
+      //   more information here, e.g. naming the field.  We used to do that.
+      //   But we can't now that FieldSet doesn't use descriptors.  Maybe this
+      //   isn't a big deal, though, since it would only really apply when using
+      //   reflection and generally people don't chain reflection setters.
       throw new IllegalArgumentException(
-        "Wrong object type used with protocol message reflection.  " +
-        "Message type \"" + field.getContainingType().getFullName() +
-        "\", field \"" +
-        (field.isExtension() ? field.getFullName() : field.getName()) +
-        "\", value was type \"" + value.getClass().getName() + "\".");
+        "Wrong object type used with protocol message reflection.");
     }
   }
 
@@ -284,17 +338,19 @@
    */
   @SuppressWarnings("unchecked")
   public boolean isInitialized() {
-    for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        if (field.isRepeated()) {
-          for (Message element : (List<Message>) entry.getValue()) {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
+      final FieldDescriptorType descriptor = entry.getKey();
+      if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+        if (descriptor.isRepeated()) {
+          for (final MessageLite element:
+               (List<MessageLite>) entry.getValue()) {
             if (!element.isInitialized()) {
               return false;
             }
           }
         } else {
-          if (!((Message) entry.getValue()).isInitialized()) {
+          if (!((MessageLite) entry.getValue()).isInitialized()) {
             return false;
           }
         }
@@ -305,59 +361,17 @@
   }
 
   /**
-   * Like {@link #isInitialized()}, but also checks for the presence of
-   * all required fields in the given type.
+   * Given a field type, return the wire type.
+   *
+   * @returns One of the {@code WIRETYPE_} constants defined in
+   *          {@link WireFormat}.
    */
-  @SuppressWarnings("unchecked")
-  public boolean isInitialized(Descriptor type) {
-    // Check that all required fields are present.
-    for (FieldDescriptor field : type.getFields()) {
-      if (field.isRequired()) {
-        if (!hasField(field)) {
-          return false;
-        }
-      }
-    }
-
-    // Check that embedded messages are initialized.
-    return isInitialized();
-  }
-
-  /** See {@link Message.Builder#mergeFrom(Message)}. */
-  @SuppressWarnings("unchecked")
-  public void mergeFrom(Message other) {
-    // Note:  We don't attempt to verify that other's fields have valid
-    //   types.  Doing so would be a losing battle.  We'd have to verify
-    //   all sub-messages as well, and we'd have to make copies of all of
-    //   them to insure that they don't change after verification (since
-    //   the Message interface itself cannot enforce immutability of
-    //   implementations).
-    // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
-    //   which allows people to make secure deep copies of messages.
-
-    for (Map.Entry<FieldDescriptor, Object> entry :
-         other.getAllFields().entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      if (field.isRepeated()) {
-        List existingValue = (List)fields.get(field);
-        if (existingValue == null) {
-          existingValue = new ArrayList();
-          fields.put(field, existingValue);
-        }
-        existingValue.addAll((List)entry.getValue());
-      } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        Message existingValue = (Message)fields.get(field);
-        if (existingValue == null) {
-          setField(field, entry.getValue());
-        } else {
-          setField(field,
-            existingValue.toBuilder()
-              .mergeFrom((Message)entry.getValue())
-              .build());
-        }
-      } else {
-        setField(field, entry.getValue());
-      }
+  static int getWireFormatForFieldType(final WireFormat.FieldType type,
+                                       boolean isPacked) {
+    if (isPacked) {
+      return WireFormat.WIRETYPE_LENGTH_DELIMITED;
+    } else {
+      return type.getWireType();
     }
   }
 
@@ -365,320 +379,211 @@
    * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
    */
   @SuppressWarnings("unchecked")
-  public void mergeFrom(FieldSet other) {
-    for (Map.Entry<FieldDescriptor, Object> entry : other.fields.entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      Object value = entry.getValue();
+  public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         other.fields.entrySet()) {
+      final FieldDescriptorType descriptor = entry.getKey();
+      final Object otherValue = entry.getValue();
 
-      if (field.isRepeated()) {
-        List existingValue = (List)fields.get(field);
-        if (existingValue == null) {
-          existingValue = new ArrayList();
-          fields.put(field, existingValue);
-        }
-        existingValue.addAll((List)value);
-      } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        Message existingValue = (Message)fields.get(field);
-        if (existingValue == null) {
-          setField(field, value);
+      if (descriptor.isRepeated()) {
+        Object value = fields.get(descriptor);
+        if (value == null) {
+          // Our list is empty, but we still need to make a defensive copy of
+          // the other list since we don't know if the other FieldSet is still
+          // mutable.
+          fields.put(descriptor, new ArrayList((List) otherValue));
         } else {
-          setField(field,
-            existingValue.toBuilder()
-              .mergeFrom((Message)value)
+          // Concatenate the lists.
+          ((List) value).addAll((List) otherValue);
+        }
+      } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+        Object value = fields.get(descriptor);
+        if (value == null) {
+          fields.put(descriptor, otherValue);
+        } else {
+          // Merge the messages.
+          fields.put(descriptor,
+              descriptor.internalMergeFrom(
+                ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
               .build());
         }
+
       } else {
-        setField(field, value);
+        fields.put(descriptor, otherValue);
       }
     }
   }
 
-  // TODO(kenton):  Move parsing code into AbstractMessage, since it no longer
-  //   uses any special knowledge from FieldSet.
+  // TODO(kenton):  Move static parsing and serialization methods into some
+  //   other class.  Probably WireFormat.
 
   /**
-   * See {@link Message.Builder#mergeFrom(CodedInputStream)}.
-   * @param builder The {@code Builder} for the target message.
+   * Read a field of any primitive type 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.
+   * @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.
    */
-  public static void mergeFrom(CodedInputStream input,
-                               UnknownFieldSet.Builder unknownFields,
-                               ExtensionRegistry extensionRegistry,
-                               Message.Builder builder)
-                               throws java.io.IOException {
-    while (true) {
-      int tag = input.readTag();
-      if (tag == 0) {
-        break;
-      }
-
-      if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
-                          builder, tag)) {
-        // end group tag
-        break;
-      }
-    }
-  }
-
-  /**
-   * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
-   * ExtensionRegistry, Message.Builder)}, but parses a single field.
-   * @param tag The tag, which should have already been read.
-   * @return {@code true} unless the tag is an end-group tag.
-   */
-  @SuppressWarnings("unchecked")
-  public static boolean mergeFieldFrom(
+  public static Object readPrimitiveField(
       CodedInputStream input,
-      UnknownFieldSet.Builder unknownFields,
-      ExtensionRegistry extensionRegistry,
-      Message.Builder builder,
-      int tag) throws java.io.IOException {
-    Descriptor type = builder.getDescriptorForType();
+      final WireFormat.FieldType type) 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  : 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  ();
 
-    if (type.getOptions().getMessageSetWireFormat() &&
-        tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
-      mergeMessageSetExtensionFromCodedStream(
-        input, unknownFields, extensionRegistry, builder);
-      return true;
+      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.");
     }
 
-    int wireType = WireFormat.getTagWireType(tag);
-    int fieldNumber = WireFormat.getTagFieldNumber(tag);
-
-    FieldDescriptor field;
-    Message defaultInstance = null;
-
-    if (type.isExtensionNumber(fieldNumber)) {
-      ExtensionRegistry.ExtensionInfo extension =
-        extensionRegistry.findExtensionByNumber(type, fieldNumber);
-      if (extension == null) {
-        field = null;
-      } else {
-        field = extension.descriptor;
-        defaultInstance = extension.defaultInstance;
-      }
-    } else {
-      field = type.findFieldByNumber(fieldNumber);
-    }
-
-    if (field == null ||
-        wireType != WireFormat.getWireFormatForField(field)) {
-      // Unknown field or wrong wire type.  Skip.
-      return unknownFields.mergeFieldFrom(tag, input);
-    } else {
-      if (field.getOptions().getPacked()) {
-        int length = input.readRawVarint32();
-        int limit = input.pushLimit(length);
-        if (field.getType() == FieldDescriptor.Type.ENUM) {
-          while (input.getBytesUntilLimit() > 0) {
-            int rawValue = input.readEnum();
-            Object value = field.getEnumType().findValueByNumber(rawValue);
-            if (value == null) {
-              // If the number isn't recognized as a valid value for this
-              // enum, drop it (don't even add it to unknownFields).
-              return true;
-            }
-            builder.addRepeatedField(field, value);
-          }
-        } else {
-          while (input.getBytesUntilLimit() > 0) {
-            Object value = input.readPrimitiveField(field.getType());
-            builder.addRepeatedField(field, value);
-          }
-        }
-        input.popLimit(limit);
-      } else {
-        Object value;
-        switch (field.getType()) {
-          case GROUP: {
-            Message.Builder subBuilder;
-            if (defaultInstance != null) {
-              subBuilder = defaultInstance.newBuilderForType();
-            } else {
-              subBuilder = builder.newBuilderForField(field);
-            }
-            if (!field.isRepeated()) {
-              subBuilder.mergeFrom((Message) builder.getField(field));
-            }
-            input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
-            value = subBuilder.build();
-            break;
-          }
-          case MESSAGE: {
-            Message.Builder subBuilder;
-            if (defaultInstance != null) {
-              subBuilder = defaultInstance.newBuilderForType();
-            } else {
-              subBuilder = builder.newBuilderForField(field);
-            }
-            if (!field.isRepeated()) {
-              subBuilder.mergeFrom((Message) builder.getField(field));
-            }
-            input.readMessage(subBuilder, extensionRegistry);
-            value = subBuilder.build();
-            break;
-          }
-          case ENUM: {
-            int rawValue = input.readEnum();
-            value = field.getEnumType().findValueByNumber(rawValue);
-            // If the number isn't recognized as a valid value for this enum,
-            // drop it.
-            if (value == null) {
-              unknownFields.mergeVarintField(fieldNumber, rawValue);
-              return true;
-            }
-            break;
-          }
-          default:
-            value = input.readPrimitiveField(field.getType());
-            break;
-        }
-
-        if (field.isRepeated()) {
-          builder.addRepeatedField(field, value);
-        } else {
-          builder.setField(field, value);
-        }
-      }
-    }
-
-    return true;
-  }
-
-  /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
-  private static void mergeMessageSetExtensionFromCodedStream(
-      CodedInputStream input,
-      UnknownFieldSet.Builder unknownFields,
-      ExtensionRegistry extensionRegistry,
-      Message.Builder builder) throws java.io.IOException {
-    Descriptor type = builder.getDescriptorForType();
-
-    // The wire format for MessageSet is:
-    //   message MessageSet {
-    //     repeated group Item = 1 {
-    //       required int32 typeId = 2;
-    //       required bytes message = 3;
-    //     }
-    //   }
-    // "typeId" is the extension's field number.  The extension can only be
-    // a message type, where "message" contains the encoded bytes of that
-    // message.
-    //
-    // In practice, we will probably never see a MessageSet item in which
-    // the message appears before the type ID, or where either field does not
-    // appear exactly once.  However, in theory such cases are valid, so we
-    // should be prepared to accept them.
-
-    int typeId = 0;
-    ByteString rawBytes = null;  // If we encounter "message" before "typeId"
-    Message.Builder subBuilder = null;
-    FieldDescriptor field = null;
-
-    while (true) {
-      int tag = input.readTag();
-      if (tag == 0) {
-        break;
-      }
-
-      if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
-        typeId = input.readUInt32();
-        // Zero is not a valid type ID.
-        if (typeId != 0) {
-          ExtensionRegistry.ExtensionInfo extension =
-            extensionRegistry.findExtensionByNumber(type, typeId);
-          if (extension != null) {
-            field = extension.descriptor;
-            subBuilder = extension.defaultInstance.newBuilderForType();
-            Message originalMessage = (Message)builder.getField(field);
-            if (originalMessage != null) {
-              subBuilder.mergeFrom(originalMessage);
-            }
-            if (rawBytes != null) {
-              // We already encountered the message.  Parse it now.
-              subBuilder.mergeFrom(
-                CodedInputStream.newInstance(rawBytes.newInput()));
-              rawBytes = null;
-            }
-          } else {
-            // Unknown extension number.  If we already saw data, put it
-            // in rawBytes.
-            if (rawBytes != null) {
-              unknownFields.mergeField(typeId,
-                UnknownFieldSet.Field.newBuilder()
-                  .addLengthDelimited(rawBytes)
-                  .build());
-              rawBytes = null;
-            }
-          }
-        }
-      } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
-        if (typeId == 0) {
-          // We haven't seen a type ID yet, so we have to store the raw bytes
-          // for now.
-          rawBytes = input.readBytes();
-        } else if (subBuilder == null) {
-          // We don't know how to parse this.  Ignore it.
-          unknownFields.mergeField(typeId,
-            UnknownFieldSet.Field.newBuilder()
-              .addLengthDelimited(input.readBytes())
-              .build());
-        } else {
-          // We already know the type, so we can parse directly from the input
-          // with no copying.  Hooray!
-          input.readMessage(subBuilder, extensionRegistry);
-        }
-      } else {
-        // Unknown tag.  Skip it.
-        if (!input.skipField(tag)) {
-          break;  // end of group
-        }
-      }
-    }
-
-    input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
-
-    if (subBuilder != null) {
-      builder.setField(field, subBuilder.build());
-    }
+    throw new RuntimeException(
+      "There is no way to get here, but the compiler thinks otherwise.");
   }
 
   /** See {@link Message#writeTo(CodedOutputStream)}. */
-  public void writeTo(CodedOutputStream output)
-                      throws java.io.IOException {
-    for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
+  public void writeTo(final CodedOutputStream output)
+                      throws IOException {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
       writeField(entry.getKey(), entry.getValue(), output);
     }
   }
 
-  /** Write a single field. */
-  public void writeField(FieldDescriptor field, Object value,
-                         CodedOutputStream output) throws java.io.IOException {
-    if (field.isExtension() &&
-        field.getContainingType().getOptions().getMessageSetWireFormat()) {
-      output.writeMessageSetExtension(field.getNumber(), (Message)value);
+  /**
+   * Like {@link #writeTo} but uses MessageSet wire format.
+   */
+  public void writeMessageSetTo(final CodedOutputStream output)
+                                throws IOException {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
+      final FieldDescriptorType descriptor = entry.getKey();
+      if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+          !descriptor.isRepeated() && !descriptor.isPacked()) {
+        output.writeMessageSetExtension(entry.getKey().getNumber(),
+                                        (MessageLite) entry.getValue());
+      } else {
+        writeField(descriptor, entry.getValue(), output);
+      }
+    }
+  }
+
+  /**
+   * Write a single tag-value pair to the stream.
+   *
+   * @param output The output stream.
+   * @param type   The field's type.
+   * @param number The field's number.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  private static void writeElement(final CodedOutputStream output,
+                                   final WireFormat.FieldType type,
+                                   final int number,
+                                   final Object value) throws IOException {
+    // Special case for groups, which need a start and end tag; other fields
+    // can just use writeTag() and writeFieldNoTag().
+    if (type == WireFormat.FieldType.GROUP) {
+      output.writeGroup(number, (MessageLite) value);
     } else {
-      if (field.isRepeated()) {
-        List valueList = (List)value;
-        if (field.getOptions().getPacked()) {
-          output.writeTag(field.getNumber(),
-                          WireFormat.WIRETYPE_LENGTH_DELIMITED);
-          // Compute the total data size so the length can be written.
-          int dataSize = 0;
-          for (Object element : valueList) {
-            dataSize += output.computeFieldSizeNoTag(field.getType(), element);
-          }
-          output.writeRawVarint32(dataSize);
-          // Write the data itself, without any tags.
-          for (Object element : valueList) {
-            output.writeFieldNoTag(field.getType(), element);
-          }
-        } else {
-          for (Object element : valueList) {
-            output.writeField(field.getType(), field.getNumber(), element);
-          }
+      output.writeTag(number, getWireFormatForFieldType(type, false));
+      writeElementNoTag(output, type, value);
+    }
+  }
+
+  /**
+   * Write a field of arbitrary type, without its tag, to the stream.
+   *
+   * @param output The output stream.
+   * @param type The field's type.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  private static void writeElementNoTag(
+      final CodedOutputStream output,
+      final WireFormat.FieldType type,
+      final Object value) throws IOException {
+    switch (type) {
+      case DOUBLE  : output.writeDoubleNoTag  ((Double     ) value); break;
+      case FLOAT   : output.writeFloatNoTag   ((Float      ) value); break;
+      case INT64   : output.writeInt64NoTag   ((Long       ) value); break;
+      case UINT64  : output.writeUInt64NoTag  ((Long       ) value); break;
+      case INT32   : output.writeInt32NoTag   ((Integer    ) value); break;
+      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 BYTES   : output.writeBytesNoTag   ((ByteString ) value); break;
+      case UINT32  : output.writeUInt32NoTag  ((Integer    ) value); break;
+      case SFIXED32: output.writeSFixed32NoTag((Integer    ) value); break;
+      case SFIXED64: output.writeSFixed64NoTag((Long       ) value); break;
+      case SINT32  : output.writeSInt32NoTag  ((Integer    ) value); break;
+      case SINT64  : output.writeSInt64NoTag  ((Long       ) value); break;
+
+      case ENUM:
+        output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
+        break;
+    }
+  }
+
+  /** Write a single field. */
+  public static void writeField(final FieldDescriptorLite<?> descriptor,
+                                final Object value,
+                                final CodedOutputStream output)
+                                throws IOException {
+    WireFormat.FieldType type = descriptor.getLiteType();
+    int number = descriptor.getNumber();
+    if (descriptor.isRepeated()) {
+      final List valueList = (List)value;
+      if (descriptor.isPacked()) {
+        output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+        // Compute the total data size so the length can be written.
+        int dataSize = 0;
+        for (final Object element : valueList) {
+          dataSize += computeElementSizeNoTag(type, element);
+        }
+        output.writeRawVarint32(dataSize);
+        // Write the data itself, without any tags.
+        for (final Object element : valueList) {
+          writeElementNoTag(output, type, element);
         }
       } else {
-        output.writeField(field.getType(), field.getNumber(), value);
+        for (final Object element : valueList) {
+          writeElement(output, type, number, element);
+        }
       }
+    } else {
+      writeElement(output, type, number, value);
     }
   }
 
@@ -688,37 +593,120 @@
    */
   public int getSerializedSize() {
     int size = 0;
-    for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      Object value = entry.getValue();
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
+      size += computeFieldSize(entry.getKey(), entry.getValue());
+    }
+    return size;
+  }
 
-      if (field.isExtension() &&
-          field.getContainingType().getOptions().getMessageSetWireFormat()) {
+  /**
+   * Like {@link #getSerializedSize} but uses MessageSet wire format.
+   */
+  public int getMessageSetSerializedSize() {
+    int size = 0;
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
+      final FieldDescriptorType descriptor = entry.getKey();
+      if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+          !descriptor.isRepeated() && !descriptor.isPacked()) {
         size += CodedOutputStream.computeMessageSetExtensionSize(
-          field.getNumber(), (Message) value);
+                  entry.getKey().getNumber(), (MessageLite) entry.getValue());
       } else {
-        if (field.isRepeated()) {
-          if (field.getOptions().getPacked()) {
-            int dataSize = 0;
-            for (Object element : (List)value) {
-              dataSize += CodedOutputStream.computeFieldSizeNoTag(
-                  field.getType(), element);
-            }
-            size += dataSize +
-                CodedOutputStream.computeTagSize(field.getNumber()) +
-                CodedOutputStream.computeRawVarint32Size(dataSize);
-          } else {
-            for (Object element : (List)value) {
-              size += CodedOutputStream.computeFieldSize(
-                  field.getType(), field.getNumber(), element);
-            }
-          }
-        } else {
-          size += CodedOutputStream.computeFieldSize(
-            field.getType(), field.getNumber(), value);
-        }
+        size += computeFieldSize(descriptor, entry.getValue());
       }
     }
     return size;
   }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * single tag/value pair of arbitrary type.
+   *
+   * @param type   The field's type.
+   * @param number The field's number.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  private static int computeElementSize(
+      final WireFormat.FieldType type,
+      final int number, final Object value) {
+    int tagSize = CodedOutputStream.computeTagSize(number);
+    if (type == WireFormat.FieldType.GROUP) {
+      tagSize *= 2;
+    }
+    return tagSize + computeElementSizeNoTag(type, value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * particular value of arbitrary type, excluding tag.
+   *
+   * @param type   The field's type.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  private static int computeElementSizeNoTag(
+      final WireFormat.FieldType type, final Object value) {
+    switch (type) {
+      // Note:  Minor violation of 80-char limit rule here because this would
+      //   actually be harder to read if we wrapped the lines.
+      case DOUBLE  : return CodedOutputStream.computeDoubleSizeNoTag  ((Double     )value);
+      case FLOAT   : return CodedOutputStream.computeFloatSizeNoTag   ((Float      )value);
+      case INT64   : return CodedOutputStream.computeInt64SizeNoTag   ((Long       )value);
+      case UINT64  : return CodedOutputStream.computeUInt64SizeNoTag  ((Long       )value);
+      case INT32   : return CodedOutputStream.computeInt32SizeNoTag   ((Integer    )value);
+      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 MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value);
+      case BYTES   : return CodedOutputStream.computeBytesSizeNoTag   ((ByteString )value);
+      case UINT32  : return CodedOutputStream.computeUInt32SizeNoTag  ((Integer    )value);
+      case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer    )value);
+      case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long       )value);
+      case SINT32  : return CodedOutputStream.computeSInt32SizeNoTag  ((Integer    )value);
+      case SINT64  : return CodedOutputStream.computeSInt64SizeNoTag  ((Long       )value);
+
+      case ENUM:
+        return CodedOutputStream.computeEnumSizeNoTag(
+            ((Internal.EnumLite) value).getNumber());
+    }
+
+    throw new RuntimeException(
+      "There is no way to get here, but the compiler thinks otherwise.");
+  }
+
+  /**
+   * Compute the number of bytes needed to encode a particular field.
+   */
+  public static int computeFieldSize(final FieldDescriptorLite<?> descriptor,
+                                     final Object value) {
+    WireFormat.FieldType type = descriptor.getLiteType();
+    int number = descriptor.getNumber();
+    if (descriptor.isRepeated()) {
+      if (descriptor.isPacked()) {
+        int dataSize = 0;
+        for (final Object element : (List)value) {
+          dataSize += computeElementSizeNoTag(type, element);
+        }
+        return dataSize +
+            CodedOutputStream.computeTagSize(number) +
+            CodedOutputStream.computeRawVarint32Size(dataSize);
+      } else {
+        int size = 0;
+        for (final Object element : (List)value) {
+          size += computeElementSize(type, number, element);
+        }
+        return size;
+      }
+    } else {
+      return computeElementSize(type, number, value);
+    }
+  }
 }
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 77c88c3..4994faa 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -36,8 +36,8 @@
 
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -69,13 +69,13 @@
   }
 
   /** Internal helper which returns a mutable map. */
-  private final Map<FieldDescriptor, Object> getAllFieldsMutable() {
-    TreeMap<FieldDescriptor, Object> result =
+  private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+    final TreeMap<FieldDescriptor, Object> result =
       new TreeMap<FieldDescriptor, Object>();
-    Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
-    for (FieldDescriptor field : descriptor.getFields()) {
+    final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+    for (final FieldDescriptor field : descriptor.getFields()) {
       if (field.isRepeated()) {
-        List value = (List) getField(field);
+        final List value = (List) getField(field);
         if (!value.isEmpty()) {
           result.put(field, value);
         }
@@ -88,8 +88,9 @@
     return result;
   }
 
+  @Override
   public boolean isInitialized() {
-    for (FieldDescriptor field : getDescriptorForType().getFields()) {
+    for (final FieldDescriptor field : getDescriptorForType().getFields()) {
       // Check that all required fields are present.
       if (field.isRequired()) {
         if (!hasField(field)) {
@@ -99,9 +100,9 @@
       // Check that embedded messages are initialized.
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         if (field.isRepeated()) {
-          @SuppressWarnings("unchecked")
+          @SuppressWarnings("unchecked") final
           List<Message> messageList = (List<Message>) getField(field);
-          for (Message element : messageList) {
+          for (final Message element : messageList) {
             if (!element.isInitialized()) {
               return false;
             }
@@ -121,20 +122,20 @@
     return Collections.unmodifiableMap(getAllFieldsMutable());
   }
 
-  public boolean hasField(Descriptors.FieldDescriptor field) {
+  public boolean hasField(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).has(this);
   }
 
-  public Object getField(FieldDescriptor field) {
+  public Object getField(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).get(this);
   }
 
-  public int getRepeatedFieldCount(FieldDescriptor field) {
+  public int getRepeatedFieldCount(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field)
       .getRepeatedCount(this);
   }
 
-  public Object getRepeatedField(FieldDescriptor field, int index) {
+  public Object getRepeatedField(final FieldDescriptor field, final int index) {
     return internalGetFieldAccessorTable().getField(field)
       .getRepeated(this, index);
   }
@@ -148,6 +149,15 @@
       extends AbstractMessage.Builder<BuilderType> {
     protected Builder() {}
 
+    // This is implemented here only to work around an apparent bug in the
+    // Java compiler and/or build system.  See bug #1898463.  The mere presence
+    // of this dummy clone() implementation makes it go away.
+    @Override
+    public BuilderType clone() {
+      throw new UnsupportedOperationException(
+          "This is supposed to be overridden by subclasses.");
+    }
+
     /**
      * Get the message being built.  We don't just pass this to the
      * constructor because it becomes null when build() is called.
@@ -163,55 +173,24 @@
       return internalGetResult().internalGetFieldAccessorTable();
     }
 
-    public BuilderType mergeFrom(Message other) {
-      if (other.getDescriptorForType() !=
-          internalGetFieldAccessorTable().descriptor) {
-        throw new IllegalArgumentException("Message type mismatch.");
-      }
-
-      for (Map.Entry<FieldDescriptor, Object> entry :
-           other.getAllFields().entrySet()) {
-        FieldDescriptor field = entry.getKey();
-        if (field.isRepeated()) {
-          // Concatenate repeated fields.
-          for (Object element : (List) entry.getValue()) {
-            addRepeatedField(field, element);
-          }
-        } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE &&
-                   hasField(field)) {
-          // Merge singular embedded messages.
-          Message oldValue = (Message) getField(field);
-          setField(field,
-            oldValue.newBuilderForType()
-              .mergeFrom(oldValue)
-              .mergeFrom((Message) entry.getValue())
-              .buildPartial());
-        } else {
-          // Just overwrite.
-          setField(field, entry.getValue());
-        }
-      }
-      return (BuilderType) this;
-    }
-
     public Descriptor getDescriptorForType() {
       return internalGetFieldAccessorTable().descriptor;
     }
 
-    public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+    public Map<FieldDescriptor, Object> getAllFields() {
       return internalGetResult().getAllFields();
     }
 
     public Message.Builder newBuilderForField(
-        Descriptors.FieldDescriptor field) {
+        final FieldDescriptor field) {
       return internalGetFieldAccessorTable().getField(field).newBuilder();
     }
 
-    public boolean hasField(Descriptors.FieldDescriptor field) {
+    public boolean hasField(final FieldDescriptor field) {
       return internalGetResult().hasField(field);
     }
 
-    public Object getField(Descriptors.FieldDescriptor field) {
+    public Object getField(final FieldDescriptor field) {
       if (field.isRepeated()) {
         // The underlying list object is still modifiable at this point.
         // Make sure not to expose the modifiable list to the caller.
@@ -222,35 +201,35 @@
       }
     }
 
-    public BuilderType setField(Descriptors.FieldDescriptor field,
-                                Object value) {
+    public BuilderType setField(final FieldDescriptor field,
+                                final Object value) {
       internalGetFieldAccessorTable().getField(field).set(this, value);
       return (BuilderType) this;
     }
 
-    public BuilderType clearField(Descriptors.FieldDescriptor field) {
+    public BuilderType clearField(final FieldDescriptor field) {
       internalGetFieldAccessorTable().getField(field).clear(this);
       return (BuilderType) this;
     }
 
-    public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+    public int getRepeatedFieldCount(final FieldDescriptor field) {
       return internalGetResult().getRepeatedFieldCount(field);
     }
 
-    public Object getRepeatedField(Descriptors.FieldDescriptor field,
-                                   int index) {
+    public Object getRepeatedField(final FieldDescriptor field,
+                                   final int index) {
       return internalGetResult().getRepeatedField(field, index);
     }
 
-    public BuilderType setRepeatedField(Descriptors.FieldDescriptor field,
-                                        int index, Object value) {
+    public BuilderType setRepeatedField(final FieldDescriptor field,
+                                        final int index, final Object value) {
       internalGetFieldAccessorTable().getField(field)
         .setRepeated(this, index, value);
       return (BuilderType) this;
     }
 
-    public BuilderType addRepeatedField(Descriptors.FieldDescriptor field,
-                                        Object value) {
+    public BuilderType addRepeatedField(final FieldDescriptor field,
+                                        final Object value) {
       internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
       return (BuilderType) this;
     }
@@ -259,13 +238,16 @@
       return internalGetResult().unknownFields;
     }
 
-    public final BuilderType setUnknownFields(UnknownFieldSet unknownFields) {
+    public final BuilderType setUnknownFields(
+        final UnknownFieldSet unknownFields) {
       internalGetResult().unknownFields = unknownFields;
       return (BuilderType) this;
     }
 
-    public final BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) {
-      GeneratedMessage result = internalGetResult();
+    @Override
+    public final BuilderType mergeUnknownFields(
+        final UnknownFieldSet unknownFields) {
+      final GeneratedMessage result = internalGetResult();
       result.unknownFields =
         UnknownFieldSet.newBuilder(result.unknownFields)
                        .mergeFrom(unknownFields)
@@ -281,36 +263,13 @@
      * Called by subclasses to parse an unknown field.
      * @return {@code true} unless the tag is an end-group tag.
      */
-    protected boolean parseUnknownField(CodedInputStream input,
-                                        UnknownFieldSet.Builder unknownFields,
-                                        ExtensionRegistry extensionRegistry,
-                                        int tag)
-                                 throws IOException {
+    protected boolean parseUnknownField(
+        final CodedInputStream input,
+        final UnknownFieldSet.Builder unknownFields,
+        final ExtensionRegistryLite extensionRegistry,
+        final int tag) throws IOException {
       return unknownFields.mergeFieldFrom(tag, input);
     }
-
-    /**
-     * Adds the {@code values} to the {@code list}.
-     *
-     * @throws NullPointerException if any of the elements of {@code values} is
-     * null.
-     */
-    protected <T> void addAll(Iterable<T> values, Collection<? super T> list) {
-      for (T value : values) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-      }
-      if (values instanceof Collection) {
-        @SuppressWarnings("unsafe")
-        Collection<T> collection = (Collection<T>) values;
-        list.addAll(collection);
-      } else {
-        for (T value : values) {
-          list.add(value);
-        }
-      }
-    }
   }
 
   // =================================================================
@@ -355,10 +314,10 @@
         MessageType extends ExtendableMessage>
       extends GeneratedMessage {
     protected ExtendableMessage() {}
-    private final FieldSet extensions = FieldSet.newFieldSet();
+    private final FieldSet<FieldDescriptor> extensions = FieldSet.newFieldSet();
 
-    private final void verifyExtensionContainingType(
-        GeneratedExtension<MessageType, ?> extension) {
+    private void verifyExtensionContainingType(
+        final GeneratedExtension<MessageType, ?> extension) {
       if (extension.getDescriptor().getContainingType() !=
           getDescriptorForType()) {
         // This can only happen if someone uses unchecked operations.
@@ -372,26 +331,33 @@
 
     /** Check if a singular extension is present. */
     public final boolean hasExtension(
-        GeneratedExtension<MessageType, ?> extension) {
+        final GeneratedExtension<MessageType, ?> extension) {
       verifyExtensionContainingType(extension);
       return extensions.hasField(extension.getDescriptor());
     }
 
     /** Get the number of elements in a repeated extension. */
     public final <Type> int getExtensionCount(
-        GeneratedExtension<MessageType, List<Type>> extension) {
+        final GeneratedExtension<MessageType, List<Type>> extension) {
       verifyExtensionContainingType(extension);
-      return extensions.getRepeatedFieldCount(extension.getDescriptor());
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      return extensions.getRepeatedFieldCount(descriptor);
     }
 
     /** Get the value of an extension. */
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
-        GeneratedExtension<MessageType, Type> extension) {
+        final GeneratedExtension<MessageType, Type> extension) {
       verifyExtensionContainingType(extension);
-      Object value = extensions.getField(extension.getDescriptor());
+      FieldDescriptor descriptor = extension.getDescriptor();
+      final Object value = extensions.getField(descriptor);
       if (value == null) {
-        return (Type) extension.getMessageDefaultInstance();
+        if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          return (Type) extension.getMessageDefaultInstance();
+        } else {
+          return (Type) extension.fromReflectionType(
+              descriptor.getDefaultValue());
+        }
       } else {
         return (Type) extension.fromReflectionType(value);
       }
@@ -400,10 +366,12 @@
     /** Get one element of a repeated extension. */
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
-        GeneratedExtension<MessageType, List<Type>> extension, int index) {
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index) {
       verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
       return (Type) extension.singularFromReflectionType(
-        extensions.getRepeatedField(extension.getDescriptor(), index));
+          extensions.getRepeatedField(descriptor, index));
     }
 
     /** Called by subclasses to check if all extensions are initialized. */
@@ -411,6 +379,7 @@
       return extensions.isInitialized();
     }
 
+    @Override
     public boolean isInitialized() {
       return super.isInitialized() && extensionsAreInitialized();
     }
@@ -425,20 +394,30 @@
       // Imagine how much simpler this code would be if Java iterators had
       // a way to get the next element without advancing the iterator.
 
-      final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
         extensions.iterator();
-      Map.Entry<FieldDescriptor, Object> next = null;
+      private Map.Entry<FieldDescriptor, Object> next;
+      private final boolean messageSetWireFormat;
 
-      private ExtensionWriter() {
+      private ExtensionWriter(final boolean messageSetWireFormat) {
         if (iter.hasNext()) {
           next = iter.next();
         }
+        this.messageSetWireFormat = messageSetWireFormat;
       }
 
-      public void writeUntil(int end, CodedOutputStream output)
+      public void writeUntil(final int end, final CodedOutputStream output)
                              throws IOException {
         while (next != null && next.getKey().getNumber() < end) {
-          extensions.writeField(next.getKey(), next.getValue(), output);
+          FieldDescriptor descriptor = next.getKey();
+          if (messageSetWireFormat && descriptor.getLiteJavaType() ==
+                  WireFormat.JavaType.MESSAGE &&
+              !descriptor.isRepeated()) {
+            output.writeMessageSetExtension(descriptor.getNumber(),
+                                            (Message) next.getValue());
+          } else {
+            FieldSet.writeField(descriptor, next.getValue(), output);
+          }
           if (iter.hasNext()) {
             next = iter.next();
           } else {
@@ -449,24 +428,32 @@
     }
 
     protected ExtensionWriter newExtensionWriter() {
-      return new ExtensionWriter();
+      return new ExtensionWriter(false);
+    }
+    protected ExtensionWriter newMessageSetExtensionWriter() {
+      return new ExtensionWriter(true);
     }
 
     /** Called by subclasses to compute the size of extensions. */
     protected int extensionsSerializedSize() {
       return extensions.getSerializedSize();
     }
+    protected int extensionsSerializedSizeAsMessageSet() {
+      return extensions.getMessageSetSerializedSize();
+    }
 
     // ---------------------------------------------------------------
     // Reflection
 
-    public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
-      Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
       result.putAll(extensions.getAllFields());
       return Collections.unmodifiableMap(result);
     }
 
-    public boolean hasField(FieldDescriptor field) {
+    @Override
+    public boolean hasField(final FieldDescriptor field) {
       if (field.isExtension()) {
         verifyContainingType(field);
         return extensions.hasField(field);
@@ -475,14 +462,19 @@
       }
     }
 
-    public Object getField(FieldDescriptor field) {
+    @Override
+    public Object getField(final FieldDescriptor field) {
       if (field.isExtension()) {
         verifyContainingType(field);
-        Object value = extensions.getField(field);
+        final Object value = extensions.getField(field);
         if (value == null) {
-          // Lacking an ExtensionRegistry, we have no way to determine the
-          // extension's real type, so we return a DynamicMessage.
-          return DynamicMessage.getDefaultInstance(field.getMessageType());
+          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            // Lacking an ExtensionRegistry, we have no way to determine the
+            // extension's real type, so we return a DynamicMessage.
+            return DynamicMessage.getDefaultInstance(field.getMessageType());
+          } else {
+            return field.getDefaultValue();
+          }
         } else {
           return value;
         }
@@ -491,7 +483,8 @@
       }
     }
 
-    public int getRepeatedFieldCount(FieldDescriptor field) {
+    @Override
+    public int getRepeatedFieldCount(final FieldDescriptor field) {
       if (field.isExtension()) {
         verifyContainingType(field);
         return extensions.getRepeatedFieldCount(field);
@@ -500,7 +493,9 @@
       }
     }
 
-    public Object getRepeatedField(FieldDescriptor field, int index) {
+    @Override
+    public Object getRepeatedField(final FieldDescriptor field,
+                                   final int index) {
       if (field.isExtension()) {
         verifyContainingType(field);
         return extensions.getRepeatedField(field, index);
@@ -509,7 +504,7 @@
       }
     }
 
-    private void verifyContainingType(FieldDescriptor field) {
+    private void verifyContainingType(final FieldDescriptor field) {
       if (field.getContainingType() != getDescriptorForType()) {
         throw new IllegalArgumentException(
           "FieldDescriptor does not match message type.");
@@ -558,70 +553,87 @@
   public abstract static class ExtendableBuilder<
         MessageType extends ExtendableMessage,
         BuilderType extends ExtendableBuilder>
-      extends GeneratedMessage.Builder<BuilderType> {
+      extends Builder<BuilderType> {
     protected ExtendableBuilder() {}
+
+    // This is implemented here only to work around an apparent bug in the
+    // Java compiler and/or build system.  See bug #1898463.  The mere presence
+    // of this dummy clone() implementation makes it go away.
+    @Override
+    public BuilderType clone() {
+      throw new UnsupportedOperationException(
+          "This is supposed to be overridden by subclasses.");
+    }
+
+    @Override
     protected abstract ExtendableMessage<MessageType> internalGetResult();
 
     /** Check if a singular extension is present. */
     public final boolean hasExtension(
-        GeneratedExtension<MessageType, ?> extension) {
+        final GeneratedExtension<MessageType, ?> extension) {
       return internalGetResult().hasExtension(extension);
     }
 
     /** Get the number of elements in a repeated extension. */
     public final <Type> int getExtensionCount(
-        GeneratedExtension<MessageType, List<Type>> extension) {
+        final GeneratedExtension<MessageType, List<Type>> extension) {
       return internalGetResult().getExtensionCount(extension);
     }
 
     /** Get the value of an extension. */
     public final <Type> Type getExtension(
-        GeneratedExtension<MessageType, Type> extension) {
+        final GeneratedExtension<MessageType, Type> extension) {
       return internalGetResult().getExtension(extension);
     }
 
     /** Get one element of a repeated extension. */
     public final <Type> Type getExtension(
-        GeneratedExtension<MessageType, List<Type>> extension, int index) {
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index) {
       return internalGetResult().getExtension(extension, index);
     }
 
     /** Set the value of an extension. */
     public final <Type> BuilderType setExtension(
-        GeneratedExtension<MessageType, Type> extension, Type value) {
-      ExtendableMessage<MessageType> message = internalGetResult();
+        final GeneratedExtension<MessageType, Type> extension,
+        final Type value) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
       message.verifyExtensionContainingType(extension);
-      message.extensions.setField(extension.getDescriptor(),
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      message.extensions.setField(descriptor,
                                   extension.toReflectionType(value));
       return (BuilderType) this;
     }
 
     /** Set the value of one element of a repeated extension. */
     public final <Type> BuilderType setExtension(
-        GeneratedExtension<MessageType, List<Type>> extension,
-        int index, Type value) {
-      ExtendableMessage<MessageType> message = internalGetResult();
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index, final Type value) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
       message.verifyExtensionContainingType(extension);
+      final FieldDescriptor descriptor = extension.getDescriptor();
       message.extensions.setRepeatedField(
-        extension.getDescriptor(), index,
+        descriptor, index,
         extension.singularToReflectionType(value));
       return (BuilderType) this;
     }
 
     /** Append a value to a repeated extension. */
     public final <Type> BuilderType addExtension(
-        GeneratedExtension<MessageType, List<Type>> extension, Type value) {
-      ExtendableMessage<MessageType> message = internalGetResult();
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final Type value) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
       message.verifyExtensionContainingType(extension);
+      final FieldDescriptor descriptor = extension.getDescriptor();
       message.extensions.addRepeatedField(
-        extension.getDescriptor(), extension.singularToReflectionType(value));
+          descriptor, extension.singularToReflectionType(value));
       return (BuilderType) this;
     }
 
     /** Clear an extension. */
     public final <Type> BuilderType clearExtension(
-        GeneratedExtension<MessageType, ?> extension) {
-      ExtendableMessage<MessageType> message = internalGetResult();
+        final GeneratedExtension<MessageType, ?> extension) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
       message.verifyExtensionContainingType(extension);
       message.extensions.clearField(extension.getDescriptor());
       return (BuilderType) this;
@@ -631,13 +643,14 @@
      * Called by subclasses to parse an unknown field or an extension.
      * @return {@code true} unless the tag is an end-group tag.
      */
-    protected boolean parseUnknownField(CodedInputStream input,
-                                        UnknownFieldSet.Builder unknownFields,
-                                        ExtensionRegistry extensionRegistry,
-                                        int tag)
-                                 throws IOException {
-      ExtendableMessage<MessageType> message = internalGetResult();
-      return message.extensions.mergeFieldFrom(
+    @Override
+    protected boolean parseUnknownField(
+        final CodedInputStream input,
+        final UnknownFieldSet.Builder unknownFields,
+        final ExtensionRegistryLite extensionRegistry,
+        final int tag) throws IOException {
+      final ExtendableMessage<MessageType> message = internalGetResult();
+      return AbstractMessage.Builder.mergeFieldFrom(
         input, unknownFields, extensionRegistry, this, tag);
     }
 
@@ -647,9 +660,11 @@
     // We don't have to override the get*() methods here because they already
     // just forward to the underlying message.
 
-    public BuilderType setField(FieldDescriptor field, Object value) {
+    @Override
+    public BuilderType setField(final FieldDescriptor field,
+                                final Object value) {
       if (field.isExtension()) {
-        ExtendableMessage<MessageType> message = internalGetResult();
+        final ExtendableMessage<MessageType> message = internalGetResult();
         message.verifyContainingType(field);
         message.extensions.setField(field, value);
         return (BuilderType) this;
@@ -658,9 +673,10 @@
       }
     }
 
-    public BuilderType clearField(Descriptors.FieldDescriptor field) {
+    @Override
+    public BuilderType clearField(final FieldDescriptor field) {
       if (field.isExtension()) {
-        ExtendableMessage<MessageType> message = internalGetResult();
+        final ExtendableMessage<MessageType> message = internalGetResult();
         message.verifyContainingType(field);
         message.extensions.clearField(field);
         return (BuilderType) this;
@@ -669,10 +685,11 @@
       }
     }
 
-    public BuilderType setRepeatedField(Descriptors.FieldDescriptor field,
-                                        int index, Object value) {
+    @Override
+    public BuilderType setRepeatedField(final FieldDescriptor field,
+                                        final int index, final Object value) {
       if (field.isExtension()) {
-        ExtendableMessage<MessageType> message = internalGetResult();
+        final ExtendableMessage<MessageType> message = internalGetResult();
         message.verifyContainingType(field);
         message.extensions.setRepeatedField(field, index, value);
         return (BuilderType) this;
@@ -681,10 +698,11 @@
       }
     }
 
-    public BuilderType addRepeatedField(Descriptors.FieldDescriptor field,
-                                        Object value) {
+    @Override
+    public BuilderType addRepeatedField(final FieldDescriptor field,
+                                        final Object value) {
       if (field.isExtension()) {
-        ExtendableMessage<MessageType> message = internalGetResult();
+        final ExtendableMessage<MessageType> message = internalGetResult();
         message.verifyContainingType(field);
         message.extensions.addRepeatedField(field, value);
         return (BuilderType) this;
@@ -693,7 +711,7 @@
       }
     }
 
-    protected final void mergeExtensionFields(ExtendableMessage other) {
+    protected final void mergeExtensionFields(final ExtendableMessage other) {
       internalGetResult().extensions.mergeFrom(other.extensions);
     }
   }
@@ -703,7 +721,8 @@
   /** For use by generated code only. */
   public static <ContainingType extends Message, Type>
       GeneratedExtension<ContainingType, Type>
-      newGeneratedExtension(FieldDescriptor descriptor, Class<Type> type) {
+      newGeneratedExtension(final FieldDescriptor descriptor,
+                            final Class<Type> type) {
     if (descriptor.isRepeated()) {
       throw new IllegalArgumentException(
         "Must call newRepeatedGeneratedExtension() for repeated types.");
@@ -715,7 +734,7 @@
   public static <ContainingType extends Message, Type>
       GeneratedExtension<ContainingType, List<Type>>
       newRepeatedGeneratedExtension(
-        FieldDescriptor descriptor, Class<Type> type) {
+        final FieldDescriptor descriptor, final Class<Type> type) {
     if (!descriptor.isRepeated()) {
       throw new IllegalArgumentException(
         "Must call newGeneratedExtension() for non-repeated types.");
@@ -753,7 +772,8 @@
     // TODO(kenton):  Find ways to avoid using Java reflection within this
     //   class.  Also try to avoid suppressing unchecked warnings.
 
-    private GeneratedExtension(FieldDescriptor descriptor, Class type) {
+    private GeneratedExtension(final FieldDescriptor descriptor,
+                               final Class type) {
       if (!descriptor.isExtension()) {
         throw new IllegalArgumentException(
           "GeneratedExtension given a regular (non-extension) field.");
@@ -808,13 +828,13 @@
      * type.
      */
     @SuppressWarnings("unchecked")
-    private Object fromReflectionType(Object value) {
+    private Object fromReflectionType(final Object value) {
       if (descriptor.isRepeated()) {
         if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
             descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
           // Must convert the whole list.
-          List result = new ArrayList();
-          for (Object element : (List) value) {
+          final List result = new ArrayList();
+          for (final Object element : (List) value) {
             result.add(singularFromReflectionType(element));
           }
           return result;
@@ -830,7 +850,7 @@
      * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
      * type, this converts a single element.
      */
-    private Object singularFromReflectionType(Object value) {
+    private Object singularFromReflectionType(final Object value) {
       switch (descriptor.getJavaType()) {
         case MESSAGE:
           if (type.isInstance(value)) {
@@ -859,12 +879,12 @@
      * type.
      */
     @SuppressWarnings("unchecked")
-    private Object toReflectionType(Object value) {
+    private Object toReflectionType(final Object value) {
       if (descriptor.isRepeated()) {
         if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
           // Must convert the whole list.
-          List result = new ArrayList();
-          for (Object element : (List) value) {
+          final List result = new ArrayList();
+          for (final Object element : (List) value) {
             result.add(singularToReflectionType(element));
           }
           return result;
@@ -880,7 +900,7 @@
      * Like {@link #toReflectionType(Object)}, but if the type is a repeated
      * type, this converts a single element.
      */
-    private Object singularToReflectionType(Object value) {
+    private Object singularToReflectionType(final Object value) {
       switch (descriptor.getJavaType()) {
         case ENUM:
           return invokeOrDie(enumGetValueDescriptor, value);
@@ -895,7 +915,7 @@
   /** Calls Class.getMethod and throws a RuntimeException if it fails. */
   @SuppressWarnings("unchecked")
   private static Method getMethodOrDie(
-      Class clazz, String name, Class... params) {
+      final Class clazz, final String name, final Class... params) {
     try {
       return clazz.getMethod(name, params);
     } catch (NoSuchMethodException e) {
@@ -907,15 +927,15 @@
 
   /** Calls invoke and throws a RuntimeException if it fails. */
   private static Object invokeOrDie(
-      Method method, Object object, Object... params) {
+      final Method method, final Object object, final Object... params) {
     try {
       return method.invoke(object, params);
     } catch (IllegalAccessException e) {
       throw new RuntimeException(
         "Couldn't use Java reflection to implement protocol message " +
         "reflection.", e);
-    } catch (java.lang.reflect.InvocationTargetException e) {
-      Throwable cause = e.getCause();
+    } catch (InvocationTargetException e) {
+      final Throwable cause = e.getCause();
       if (cause instanceof RuntimeException) {
         throw (RuntimeException) cause;
       } else if (cause instanceof Error) {
@@ -944,15 +964,15 @@
      * @param builderClass   The builder type.
      */
     public FieldAccessorTable(
-        Descriptor descriptor,
-        String[] camelCaseNames,
-        Class<? extends GeneratedMessage> messageClass,
-        Class<? extends GeneratedMessage.Builder> builderClass) {
+        final Descriptor descriptor,
+        final String[] camelCaseNames,
+        final Class<? extends GeneratedMessage> messageClass,
+        final Class<? extends Builder> builderClass) {
       this.descriptor = descriptor;
       fields = new FieldAccessor[descriptor.getFields().size()];
 
       for (int i = 0; i < fields.length; i++) {
-        FieldDescriptor field = descriptor.getFields().get(i);
+        final FieldDescriptor field = descriptor.getFields().get(i);
         if (field.isRepeated()) {
           if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
             fields[i] = new RepeatedMessageFieldAccessor(
@@ -983,7 +1003,7 @@
     private final FieldAccessor[] fields;
 
     /** Get the FieldAccessor for a particular field. */
-    private FieldAccessor getField(FieldDescriptor field) {
+    private FieldAccessor getField(final FieldDescriptor field) {
       if (field.getContainingType() != descriptor) {
         throw new IllegalArgumentException(
           "FieldDescriptor does not match message type.");
@@ -1000,16 +1020,16 @@
      * Abstract interface that provides access to a single field.  This is
      * implemented differently depending on the field type and cardinality.
      */
-    private static interface FieldAccessor {
+    private interface FieldAccessor {
       Object get(GeneratedMessage message);
-      void set(GeneratedMessage.Builder builder, Object value);
+      void set(Builder builder, Object value);
       Object getRepeated(GeneratedMessage message, int index);
-      void setRepeated(GeneratedMessage.Builder builder,
+      void setRepeated(Builder builder,
                        int index, Object value);
-      void addRepeated(GeneratedMessage.Builder builder, Object value);
+      void addRepeated(Builder builder, Object value);
       boolean has(GeneratedMessage message);
       int getRepeatedCount(GeneratedMessage message);
-      void clear(GeneratedMessage.Builder builder);
+      void clear(Builder builder);
       Message.Builder newBuilder();
     }
 
@@ -1017,9 +1037,9 @@
 
     private static class SingularFieldAccessor implements FieldAccessor {
       SingularFieldAccessor(
-          FieldDescriptor descriptor, String camelCaseName,
-          Class<? extends GeneratedMessage> messageClass,
-          Class<? extends GeneratedMessage.Builder> builderClass) {
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
         getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
         type = getMethod.getReturnType();
         setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
@@ -1031,39 +1051,40 @@
       // Note:  We use Java reflection to call public methods rather than
       //   access private fields directly as this avoids runtime security
       //   checks.
-      Class type;
-      Method getMethod;
-      Method setMethod;
-      Method hasMethod;
-      Method clearMethod;
+      protected final Class type;
+      protected final Method getMethod;
+      protected final Method setMethod;
+      protected final Method hasMethod;
+      protected final Method clearMethod;
 
-      public Object get(GeneratedMessage message) {
+      public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
-      public void set(GeneratedMessage.Builder builder, Object value) {
+      public void set(final Builder builder, final Object value) {
         invokeOrDie(setMethod, builder, value);
       }
-      public Object getRepeated(GeneratedMessage message, int index) {
+      public Object getRepeated(final GeneratedMessage message,
+                                final int index) {
         throw new UnsupportedOperationException(
           "getRepeatedField() called on a singular field.");
       }
-      public void setRepeated(GeneratedMessage.Builder builder,
-                              int index, Object value) {
+      public void setRepeated(final Builder builder,
+                              final int index, final Object value) {
         throw new UnsupportedOperationException(
           "setRepeatedField() called on a singular field.");
       }
-      public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+      public void addRepeated(final Builder builder, final Object value) {
         throw new UnsupportedOperationException(
           "addRepeatedField() called on a singular field.");
       }
-      public boolean has(GeneratedMessage message) {
+      public boolean has(final GeneratedMessage message) {
         return (Boolean) invokeOrDie(hasMethod, message);
       }
-      public int getRepeatedCount(GeneratedMessage message) {
+      public int getRepeatedCount(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldSize() called on a singular field.");
       }
-      public void clear(GeneratedMessage.Builder builder) {
+      public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
       public Message.Builder newBuilder() {
@@ -1074,10 +1095,11 @@
 
     private static class RepeatedFieldAccessor implements FieldAccessor {
       RepeatedFieldAccessor(
-          FieldDescriptor descriptor, String camelCaseName,
-          Class<? extends GeneratedMessage> messageClass,
-          Class<? extends GeneratedMessage.Builder> builderClass) {
-        getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List");
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
+        getMethod = getMethodOrDie(messageClass,
+                                   "get" + camelCaseName + "List");
 
         getRepeatedMethod =
           getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
@@ -1093,45 +1115,46 @@
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
       }
 
-      Class type;
-      Method getMethod;
-      Method getRepeatedMethod;
-      Method setRepeatedMethod;
-      Method addRepeatedMethod;
-      Method getCountMethod;
-      Method clearMethod;
+      protected final Class type;
+      protected final Method getMethod;
+      protected final Method getRepeatedMethod;
+      protected final Method setRepeatedMethod;
+      protected final Method addRepeatedMethod;
+      protected final Method getCountMethod;
+      protected final Method clearMethod;
 
-      public Object get(GeneratedMessage message) {
+      public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
-      public void set(GeneratedMessage.Builder builder, Object value) {
+      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.
         // 2) Insures that the caller cannot modify the list later on and
         //    have the modifications be reflected in the message.
         clear(builder);
-        for (Object element : (List) value) {
+        for (final Object element : (List) value) {
           addRepeated(builder, element);
         }
       }
-      public Object getRepeated(GeneratedMessage message, int index) {
+      public Object getRepeated(final GeneratedMessage message,
+                                final int index) {
         return invokeOrDie(getRepeatedMethod, message, index);
       }
-      public void setRepeated(GeneratedMessage.Builder builder,
-                              int index, Object value) {
+      public void setRepeated(final Builder builder,
+                              final int index, final Object value) {
         invokeOrDie(setRepeatedMethod, builder, index, value);
       }
-      public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+      public void addRepeated(final Builder builder, final Object value) {
         invokeOrDie(addRepeatedMethod, builder, value);
       }
-      public boolean has(GeneratedMessage message) {
+      public boolean has(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
           "hasField() called on a singular field.");
       }
-      public int getRepeatedCount(GeneratedMessage message) {
+      public int getRepeatedCount(final GeneratedMessage message) {
         return (Integer) invokeOrDie(getCountMethod, message);
       }
-      public void clear(GeneratedMessage.Builder builder) {
+      public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
       public Message.Builder newBuilder() {
@@ -1145,9 +1168,9 @@
     private static final class SingularEnumFieldAccessor
         extends SingularFieldAccessor {
       SingularEnumFieldAccessor(
-          FieldDescriptor descriptor, String camelCaseName,
-          Class<? extends GeneratedMessage> messageClass,
-          Class<? extends GeneratedMessage.Builder> builderClass) {
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -1159,10 +1182,12 @@
       private Method valueOfMethod;
       private Method getValueDescriptorMethod;
 
-      public Object get(GeneratedMessage message) {
+      @Override
+      public Object get(final GeneratedMessage message) {
         return invokeOrDie(getValueDescriptorMethod, super.get(message));
       }
-      public void set(GeneratedMessage.Builder builder, Object value) {
+      @Override
+      public void set(final Builder builder, final Object value) {
         super.set(builder, invokeOrDie(valueOfMethod, null, value));
       }
     }
@@ -1170,9 +1195,9 @@
     private static final class RepeatedEnumFieldAccessor
         extends RepeatedFieldAccessor {
       RepeatedEnumFieldAccessor(
-          FieldDescriptor descriptor, String camelCaseName,
-          Class<? extends GeneratedMessage> messageClass,
-          Class<? extends GeneratedMessage.Builder> builderClass) {
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -1181,26 +1206,32 @@
           getMethodOrDie(type, "getValueDescriptor");
       }
 
-      private Method valueOfMethod;
-      private Method getValueDescriptorMethod;
+      private final Method valueOfMethod;
+      private final Method getValueDescriptorMethod;
 
+      @Override
       @SuppressWarnings("unchecked")
-      public Object get(GeneratedMessage message) {
-        List newList = new ArrayList();
-        for (Object element : (List) super.get(message)) {
+      public Object get(final GeneratedMessage message) {
+        final List newList = new ArrayList();
+        for (final Object element : (List) super.get(message)) {
           newList.add(invokeOrDie(getValueDescriptorMethod, element));
         }
         return Collections.unmodifiableList(newList);
       }
-      public Object getRepeated(GeneratedMessage message, int index) {
+      @Override
+      public Object getRepeated(final GeneratedMessage message,
+                                final int index) {
         return invokeOrDie(getValueDescriptorMethod,
           super.getRepeated(message, index));
       }
-      public void setRepeated(GeneratedMessage.Builder builder,
-                              int index, Object value) {
-        super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value));
+      @Override
+      public void setRepeated(final Builder builder,
+                              final int index, final Object value) {
+        super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
+                          value));
       }
-      public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+      @Override
+      public void addRepeated(final Builder builder, final Object value) {
         super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
       }
     }
@@ -1210,17 +1241,17 @@
     private static final class SingularMessageFieldAccessor
         extends SingularFieldAccessor {
       SingularMessageFieldAccessor(
-          FieldDescriptor descriptor, String camelCaseName,
-          Class<? extends GeneratedMessage> messageClass,
-          Class<? extends GeneratedMessage.Builder> builderClass) {
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
       }
 
-      private Method newBuilderMethod;
+      private final Method newBuilderMethod;
 
-      private Object coerceType(Object value) {
+      private Object coerceType(final Object value) {
         if (type.isInstance(value)) {
           return value;
         } else {
@@ -1233,9 +1264,11 @@
         }
       }
 
-      public void set(GeneratedMessage.Builder builder, Object value) {
+      @Override
+      public void set(final Builder builder, final Object value) {
         super.set(builder, coerceType(value));
       }
+      @Override
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
@@ -1244,17 +1277,17 @@
     private static final class RepeatedMessageFieldAccessor
         extends RepeatedFieldAccessor {
       RepeatedMessageFieldAccessor(
-          FieldDescriptor descriptor, String camelCaseName,
-          Class<? extends GeneratedMessage> messageClass,
-          Class<? extends GeneratedMessage.Builder> builderClass) {
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
       }
 
-      private Method newBuilderMethod;
+      private final Method newBuilderMethod;
 
-      private Object coerceType(Object value) {
+      private Object coerceType(final Object value) {
         if (type.isInstance(value)) {
           return value;
         } else {
@@ -1267,13 +1300,16 @@
         }
       }
 
-      public void setRepeated(GeneratedMessage.Builder builder,
-                              int index, Object value) {
+      @Override
+      public void setRepeated(final Builder builder,
+                              final int index, final Object value) {
         super.setRepeated(builder, index, coerceType(value));
       }
-      public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+      @Override
+      public void addRepeated(final Builder builder, final Object value) {
         super.addRepeated(builder, coerceType(value));
       }
+      @Override
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
new file mode 100644
index 0000000..c68414b
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -0,0 +1,539 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Lite version of {@link GeneratedMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessageLite extends AbstractMessageLite {
+  protected GeneratedMessageLite() {}
+
+  @SuppressWarnings("unchecked")
+  public abstract static class Builder<MessageType extends GeneratedMessageLite,
+                                       BuilderType extends Builder>
+      extends AbstractMessageLite.Builder<BuilderType> {
+    protected Builder() {}
+
+    // This is implemented here only to work around an apparent bug in the
+    // Java compiler and/or build system.  See bug #1898463.  The mere presence
+    // of this dummy clone() implementation makes it go away.
+    @Override
+    public BuilderType clone() {
+      throw new UnsupportedOperationException(
+          "This is supposed to be overridden by subclasses.");
+    }
+
+    /** All subclasses implement this. */
+    public abstract BuilderType mergeFrom(MessageType message);
+
+    // Defined here for return type covariance.
+    public abstract MessageType getDefaultInstanceForType();
+
+    /**
+     * Get the message being built.  We don't just pass this to the
+     * constructor because it becomes null when build() is called.
+     */
+    protected abstract MessageType internalGetResult();
+
+    /**
+     * Called by subclasses to parse an unknown field.
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    protected boolean parseUnknownField(
+        final CodedInputStream input,
+        final ExtensionRegistryLite extensionRegistry,
+        final int tag) throws IOException {
+      return input.skipField(tag);
+    }
+  }
+
+  // =================================================================
+  // Extensions-related stuff
+
+  /**
+   * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
+   */
+  public abstract static class ExtendableMessage<
+        MessageType extends ExtendableMessage<MessageType>>
+      extends GeneratedMessageLite {
+    protected ExtendableMessage() {}
+    private final FieldSet<ExtensionDescriptor> extensions =
+        FieldSet.newFieldSet();
+
+    private void verifyExtensionContainingType(
+        final GeneratedExtension<MessageType, ?> extension) {
+      if (extension.getContainingTypeDefaultInstance() !=
+          getDefaultInstanceForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "This extension is for a different message type.  Please make " +
+          "sure that you are not suppressing any generics type warnings.");
+      }
+    }
+
+    /** Check if a singular extension is present. */
+    public final boolean hasExtension(
+        final GeneratedExtension<MessageType, ?> extension) {
+      verifyExtensionContainingType(extension);
+      return extensions.hasField(extension.descriptor);
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    public final <Type> int getExtensionCount(
+        final GeneratedExtension<MessageType, List<Type>> extension) {
+      verifyExtensionContainingType(extension);
+      return extensions.getRepeatedFieldCount(extension.descriptor);
+    }
+
+    /** Get the value of an extension. */
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
+      verifyExtensionContainingType(extension);
+      final Object value = extensions.getField(extension.descriptor);
+      if (value == null) {
+        return extension.defaultValue;
+      } else {
+        return (Type) value;
+      }
+    }
+
+    /** Get one element of a repeated extension. */
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index) {
+      verifyExtensionContainingType(extension);
+      return (Type) extensions.getRepeatedField(extension.descriptor, index);
+    }
+
+    /** Called by subclasses to check if all extensions are initialized. */
+    protected boolean extensionsAreInitialized() {
+      return extensions.isInitialized();
+    }
+
+    /**
+     * Used by subclasses to serialize extensions.  Extension ranges may be
+     * interleaved with field numbers, but we must write them in canonical
+     * (sorted by field number) order.  ExtensionWriter helps us write
+     * individual ranges of extensions at once.
+     */
+    protected class ExtensionWriter {
+      // Imagine how much simpler this code would be if Java iterators had
+      // a way to get the next element without advancing the iterator.
+
+      private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter =
+            extensions.iterator();
+      private Map.Entry<ExtensionDescriptor, Object> next;
+      private final boolean messageSetWireFormat;
+
+      private ExtensionWriter(boolean messageSetWireFormat) {
+        if (iter.hasNext()) {
+          next = iter.next();
+        }
+        this.messageSetWireFormat = messageSetWireFormat;
+      }
+
+      public void writeUntil(final int end, final CodedOutputStream output)
+                             throws IOException {
+        while (next != null && next.getKey().getNumber() < end) {
+          ExtensionDescriptor extension = next.getKey();
+          if (messageSetWireFormat && extension.getLiteJavaType() ==
+                  WireFormat.JavaType.MESSAGE &&
+              !extension.isRepeated()) {
+            output.writeMessageSetExtension(extension.getNumber(),
+                                            (MessageLite) next.getValue());
+          } else {
+            FieldSet.writeField(extension, next.getValue(), output);
+          }
+          if (iter.hasNext()) {
+            next = iter.next();
+          } else {
+            next = null;
+          }
+        }
+      }
+    }
+
+    protected ExtensionWriter newExtensionWriter() {
+      return new ExtensionWriter(false);
+    }
+    protected ExtensionWriter newMessageSetExtensionWriter() {
+      return new ExtensionWriter(true);
+    }
+
+    /** Called by subclasses to compute the size of extensions. */
+    protected int extensionsSerializedSize() {
+      return extensions.getSerializedSize();
+    }
+    protected int extensionsSerializedSizeAsMessageSet() {
+      return extensions.getMessageSetSerializedSize();
+    }
+  }
+
+  /**
+   * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}.
+   */
+  @SuppressWarnings("unchecked")
+  public abstract static class ExtendableBuilder<
+        MessageType extends ExtendableMessage<MessageType>,
+        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+      extends Builder<MessageType, BuilderType> {
+    protected ExtendableBuilder() {}
+
+    // This is implemented here only to work around an apparent bug in the
+    // Java compiler and/or build system.  See bug #1898463.  The mere presence
+    // of this dummy clone() implementation makes it go away.
+    @Override
+    public BuilderType clone() {
+      throw new UnsupportedOperationException(
+          "This is supposed to be overridden by subclasses.");
+    }
+
+    @Override
+    protected abstract MessageType internalGetResult();
+
+    /** Check if a singular extension is present. */
+    public final boolean hasExtension(
+        final GeneratedExtension<MessageType, ?> extension) {
+      return internalGetResult().hasExtension(extension);
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    public final <Type> int getExtensionCount(
+        final GeneratedExtension<MessageType, List<Type>> extension) {
+      return internalGetResult().getExtensionCount(extension);
+    }
+
+    /** Get the value of an extension. */
+    public final <Type> Type getExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
+      return internalGetResult().getExtension(extension);
+    }
+
+    /** Get one element of a repeated extension. */
+    public final <Type> Type getExtension(
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index) {
+      return internalGetResult().getExtension(extension, index);
+    }
+
+    /** Set the value of an extension. */
+    public final <Type> BuilderType setExtension(
+        final GeneratedExtension<MessageType, Type> extension,
+        final Type value) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
+      message.verifyExtensionContainingType(extension);
+      message.extensions.setField(extension.descriptor, value);
+      return (BuilderType) this;
+    }
+
+    /** Set the value of one element of a repeated extension. */
+    public final <Type> BuilderType setExtension(
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index, final Type value) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
+      message.verifyExtensionContainingType(extension);
+      message.extensions.setRepeatedField(extension.descriptor, index, value);
+      return (BuilderType) this;
+    }
+
+    /** Append a value to a repeated extension. */
+    public final <Type> BuilderType addExtension(
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final Type value) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
+      message.verifyExtensionContainingType(extension);
+      message.extensions.addRepeatedField(extension.descriptor, value);
+      return (BuilderType) this;
+    }
+
+    /** Clear an extension. */
+    public final <Type> BuilderType clearExtension(
+        final GeneratedExtension<MessageType, ?> extension) {
+      final ExtendableMessage<MessageType> message = internalGetResult();
+      message.verifyExtensionContainingType(extension);
+      message.extensions.clearField(extension.descriptor);
+      return (BuilderType) this;
+    }
+
+    /**
+     * Called by subclasses to parse an unknown field or an extension.
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    @Override
+    protected boolean parseUnknownField(
+        final CodedInputStream input,
+        final ExtensionRegistryLite extensionRegistry,
+        final int tag) throws IOException {
+      final FieldSet<ExtensionDescriptor> extensions =
+          internalGetResult().extensions;
+
+      final int wireType = WireFormat.getTagWireType(tag);
+      final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+      final GeneratedExtension<MessageType, ?> extension =
+        extensionRegistry.findLiteExtensionByNumber(
+            getDefaultInstanceForType(), fieldNumber);
+
+      if (extension == null || wireType !=
+            FieldSet.getWireFormatForFieldType(
+                extension.descriptor.getLiteType(),
+                extension.descriptor.isPacked())) {
+        // Unknown field or wrong wire type.  Skip.
+        return input.skipField(tag);
+      }
+
+      if (extension.descriptor.isPacked()) {
+        final int length = input.readRawVarint32();
+        final int limit = input.pushLimit(length);
+        if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+          while (input.getBytesUntilLimit() > 0) {
+            final int rawValue = input.readEnum();
+            final Object value =
+                extension.descriptor.getEnumType().findValueByNumber(rawValue);
+            if (value == null) {
+              // If the number isn't recognized as a valid value for this
+              // enum, drop it (don't even add it to unknownFields).
+              return true;
+            }
+            extensions.addRepeatedField(extension.descriptor, value);
+          }
+        } else {
+          while (input.getBytesUntilLimit() > 0) {
+            final Object value =
+              FieldSet.readPrimitiveField(input,
+                                          extension.descriptor.getLiteType());
+            extensions.addRepeatedField(extension.descriptor, value);
+          }
+        }
+        input.popLimit(limit);
+      } else {
+        final Object value;
+        switch (extension.descriptor.getLiteJavaType()) {
+          case MESSAGE: {
+            MessageLite.Builder subBuilder = null;
+            if (!extension.descriptor.isRepeated()) {
+              MessageLite existingValue =
+                  (MessageLite) extensions.getField(extension.descriptor);
+              if (existingValue != null) {
+                subBuilder = existingValue.toBuilder();
+              }
+            }
+            if (subBuilder == null) {
+              subBuilder = extension.messageDefaultInstance.newBuilderForType();
+            }
+            if (extension.descriptor.getLiteType() ==
+                WireFormat.FieldType.GROUP) {
+              input.readGroup(extension.getNumber(),
+                              subBuilder, extensionRegistry);
+            } else {
+              input.readMessage(subBuilder, extensionRegistry);
+            }
+            value = subBuilder.build();
+            break;
+          }
+          case ENUM:
+            final int rawValue = input.readEnum();
+            value = extension.descriptor.getEnumType()
+                             .findValueByNumber(rawValue);
+            // If the number isn't recognized as a valid value for this enum,
+            // drop it.
+            if (value == null) {
+              return true;
+            }
+            break;
+          default:
+            value = FieldSet.readPrimitiveField(input,
+                extension.descriptor.getLiteType());
+            break;
+        }
+
+        if (extension.descriptor.isRepeated()) {
+          extensions.addRepeatedField(extension.descriptor, value);
+        } else {
+          extensions.setField(extension.descriptor, value);
+        }
+      }
+
+      return true;
+    }
+
+    protected final void mergeExtensionFields(final MessageType other) {
+      internalGetResult().extensions.mergeFrom(other.extensions);
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  /** For use by generated code only. */
+  public static <ContainingType extends MessageLite, Type>
+      GeneratedExtension<ContainingType, Type>
+      newGeneratedExtension(
+        final ContainingType containingTypeDefaultInstance,
+        final Type defaultValue,
+        final MessageLite messageDefaultInstance,
+        final Internal.EnumLiteMap<?> enumTypeMap,
+        final int number,
+        final WireFormat.FieldType type) {
+    return new GeneratedExtension<ContainingType, Type>(
+      containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
+      new ExtensionDescriptor(enumTypeMap, number, type,
+        false /* isRepeated */, false /* isPacked */));
+  }
+
+  /** For use by generated code only. */
+  public static <ContainingType extends MessageLite, Type>
+      GeneratedExtension<ContainingType, List<Type>>
+      newRepeatedGeneratedExtension(
+        final ContainingType containingTypeDefaultInstance,
+        final MessageLite messageDefaultInstance,
+        final Internal.EnumLiteMap<?> enumTypeMap,
+        final int number,
+        final WireFormat.FieldType type,
+        final boolean isPacked) {
+    return new GeneratedExtension<ContainingType, List<Type>>(
+      containingTypeDefaultInstance, Collections.<Type>emptyList(),
+      messageDefaultInstance,
+      new ExtensionDescriptor(
+        enumTypeMap, number, type, true /* isRepeated */, isPacked));
+  }
+
+  private static final class ExtensionDescriptor
+      implements FieldSet.FieldDescriptorLite<
+        ExtensionDescriptor> {
+    private ExtensionDescriptor(
+        final Internal.EnumLiteMap<?> enumTypeMap,
+        final int number,
+        final WireFormat.FieldType type,
+        final boolean isRepeated,
+        final boolean isPacked) {
+      this.enumTypeMap = enumTypeMap;
+      this.number = number;
+      this.type = type;
+      this.isRepeated = isRepeated;
+      this.isPacked = isPacked;
+    }
+
+    private final Internal.EnumLiteMap<?> enumTypeMap;
+    private final int number;
+    private final WireFormat.FieldType type;
+    private final boolean isRepeated;
+    private final boolean isPacked;
+
+    public int getNumber() {
+      return number;
+    }
+
+    public WireFormat.FieldType getLiteType() {
+      return type;
+    }
+
+    public WireFormat.JavaType getLiteJavaType() {
+      return type.getJavaType();
+    }
+
+    public boolean isRepeated() {
+      return isRepeated;
+    }
+
+    public boolean isPacked() {
+      return isPacked;
+    }
+
+    public Internal.EnumLiteMap<?> getEnumType() {
+      return enumTypeMap;
+    }
+
+    @SuppressWarnings("unchecked")
+    public MessageLite.Builder internalMergeFrom(
+        MessageLite.Builder to, MessageLite from) {
+      return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
+    }
+
+    public int compareTo(ExtensionDescriptor other) {
+      return number - other.number;
+    }
+  }
+
+  /**
+   * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
+   *
+   * Users should ignore the contents of this class and only use objects of
+   * this type as parameters to extension accessors and ExtensionRegistry.add().
+   */
+  public static final class GeneratedExtension<
+      ContainingType extends MessageLite, Type> {
+    private GeneratedExtension(
+        final ContainingType containingTypeDefaultInstance,
+        final Type defaultValue,
+        final MessageLite messageDefaultInstance,
+        final ExtensionDescriptor descriptor) {
+      this.containingTypeDefaultInstance = containingTypeDefaultInstance;
+      this.defaultValue = defaultValue;
+      this.messageDefaultInstance = messageDefaultInstance;
+      this.descriptor = descriptor;
+    }
+
+    private final ContainingType containingTypeDefaultInstance;
+    private final Type defaultValue;
+    private final MessageLite messageDefaultInstance;
+    private final ExtensionDescriptor descriptor;
+
+    /**
+     * Default instance of the type being extended, used to identify that type.
+     */
+    public ContainingType getContainingTypeDefaultInstance() {
+      return containingTypeDefaultInstance;
+    }
+
+    /** Get the field number. */
+    public int getNumber() {
+      return descriptor.getNumber();
+    }
+
+    /**
+     * If the extension is an embedded message, this is the default instance of
+     * that type.
+     */
+    public MessageLite getMessageDefaultInstance() {
+      return messageDefaultInstance;
+    }
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
new file mode 100644
index 0000000..ba8e6ae
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -0,0 +1,194 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * The classes contained within are used internally by the Protocol Buffer
+ * library and generated message implementations. They are public only because
+ * those generated messages do not reside in the {@code protobuf} package.
+ * Others should not use this class directly.
+ *
+ * @author cyrusn@google.com (Cyrus Najmabadi)
+ */
+public class Internal {
+  /**
+   * Implementation of a Queue designed to have as little overhead as possible.
+   * No guarantees are made as to the order you will get values back from the
+   * queue. Currently it is a Last-In-First-Out implementation, but that may
+   * change in the future.
+   *
+   * Duplicate values are allowed, as are null values.
+   *
+   * Not threadsafe.
+   *
+   * @author cyrusn@google.com (Cyrus Najmabadi)
+   */
+  public static final class QuickQueue<T> {
+    @SuppressWarnings("unchecked")
+    private T[] array = (T[]) new Object[16];
+    private int size;
+
+    /**
+     * Adds a value to the queue.
+     *
+     * @param value The value to add to the queue.
+     */
+    public void offer(final T value) {
+      if (size == array.length) {
+        // I'd like to use Arrays.copy here. However, it is currently
+        // unavailable
+        // on android. So, for now, we just use the tried and true arraycopy
+        // technique.
+        @SuppressWarnings("unchecked")
+        final T[] copy = (T[]) new Object[size * 2];
+        System.arraycopy(array, 0, copy, 0, array.length);
+        array = copy;
+      }
+
+      array[size++] = value;
+    }
+
+    /**
+     * Removes some previously added value to the queue, or {@code null} if the
+     * queue is empty.
+     *
+     * @return An existing value in the queue, or {@code null} if the queue is
+     *         empty.
+     */
+    public T poll() {
+      if (size == 0) {
+        return null;
+      }
+
+      final T result = array[--size];
+      // make sure we null out the entry so that we're not keeping anything
+      // alive unnecessarily.
+      array[size] = null;
+
+      return result;
+    }
+  }
+
+  /**
+   * Instances of this class will provide a unique {@code QuickQueue} to each
+   * thread that accesses it. Very useful for providing free lists without
+   * needing to take any locks.
+   *
+   * @author cyrusn@google.com (Cyrus Najmabadi)
+   */
+  public static final class ThreadLocalQuickQueue<T>
+      extends ThreadLocal<QuickQueue<T>> {
+    @Override
+    protected QuickQueue<T> initialValue() {
+      return new QuickQueue<T>();
+    }
+  }
+
+  /**
+   * Helper called by generated code to construct default values for string
+   * fields.
+   * <p>
+   * The protocol compiler does not actually contain a UTF-8 decoder -- it
+   * just pushes UTF-8-encoded text around without touching it.  The one place
+   * where this presents a problem is when generating Java string literals.
+   * Unicode characters in the string literal would normally need to be encoded
+   * using a Unicode escape sequence, which would require decoding them.
+   * To get around this, protoc instead embeds the UTF-8 bytes into the
+   * generated code and leaves it to the runtime library to decode them.
+   * <p>
+   * It gets worse, though.  If protoc just generated a byte array, like:
+   *   new byte[] {0x12, 0x34, 0x56, 0x78}
+   * Java actually generates *code* which allocates an array and then fills
+   * in each value.  This is much less efficient than just embedding the bytes
+   * directly into the bytecode.  To get around this, we need another
+   * work-around.  String literals are embedded directly, so protoc actually
+   * generates a string literal corresponding to the bytes.  The easiest way
+   * to do this is to use the ISO-8859-1 character set, which corresponds to
+   * the first 256 characters of the Unicode range.  Protoc can then use
+   * good old CEscape to generate the string.
+   * <p>
+   * So we have a string literal which represents a set of bytes which
+   * represents another string.  This function -- stringDefaultValue --
+   * converts from the generated string to the string we actually want.  The
+   * generated code calls this automatically.
+   */
+  public static String stringDefaultValue(String bytes) {
+    try {
+      return new String(bytes.getBytes("ISO-8859-1"), "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      // This should never happen since all JVMs are required to implement
+      // both of the above character sets.
+      throw new IllegalStateException(
+          "Java VM does not support a standard character set.", e);
+    }
+  }
+
+  /**
+   * Helper called by generated code to construct default values for bytes
+   * fields.
+   * <p>
+   * This is a lot like {@link #stringDefaultValue}, but for bytes fields.
+   * In this case we only need the second of the two hacks -- allowing us to
+   * embed raw bytes as a string literal with ISO-8859-1 encoding.
+   */
+  public static ByteString bytesDefaultValue(String bytes) {
+    try {
+      return ByteString.copyFrom(bytes.getBytes("ISO-8859-1"));
+    } catch (UnsupportedEncodingException e) {
+      // This should never happen since all JVMs are required to implement
+      // ISO-8859-1.
+      throw new IllegalStateException(
+          "Java VM does not support a standard character set.", e);
+    }
+  }
+
+  /**
+   * Interface for an enum value or value descriptor, to be used in FieldSet.
+   * The lite library stores enum values directly in FieldSets but the full
+   * library stores EnumValueDescriptors in order to better support reflection.
+   */
+  public interface EnumLite {
+    int getNumber();
+  }
+
+  /**
+   * Interface for an object which maps integers to {@link EnumLite}s.
+   * {@link Descriptors.EnumDescriptor} implements this interface by mapping
+   * numbers to {@link Descriptors.EnumValueDescriptor}s.  Additionally,
+   * every generated enum type has a static method internalGetValueMap() which
+   * returns an implementation of this type that maps numbers to enum values.
+   */
+  public interface EnumLiteMap<T extends EnumLite> {
+    T findValueByNumber(int number);
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 593be0e..90f7ffb 100644
--- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -39,7 +39,9 @@
  * @author kenton@google.com Kenton Varda
  */
 public class InvalidProtocolBufferException extends IOException {
-  public InvalidProtocolBufferException(String description) {
+  private static final long serialVersionUID = -1616151763072450476L;
+
+  public InvalidProtocolBufferException(final String description) {
     super(description);
   }
 
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index a595123..c11abdc 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -33,17 +33,22 @@
 
 package com.google.protobuf;
 
-import java.io.InputStream;
 import java.io.IOException;
-import java.io.OutputStream;
+import java.io.InputStream;
 import java.util.Map;
 
 /**
  * Abstract interface implemented by Protocol Message objects.
+ * <p>
+ * See also {@link MessageLite}, which defines most of the methods that typical
+ * users care about.  {@link Message} adds to it methods that are not available
+ * in the "lite" runtime.  The biggest added features are introspection and
+ * reflection -- i.e., getting descriptors for the message type and accessing
+ * the field values dynamically.
  *
  * @author kenton@google.com Kenton Varda
  */
-public interface Message {
+public interface Message extends MessageLite {
   /**
    * Get the message's type's descriptor.  This differs from the
    * {@code getDescriptor()} method of generated message classes in that
@@ -53,14 +58,7 @@
    */
   Descriptors.Descriptor getDescriptorForType();
 
-  /**
-   * Get an instance of the type with all fields set to their default values.
-   * This may or may not be a singleton.  This differs from the
-   * {@code getDefaultInstance()} method of generated message classes in that
-   * this method is an abstract method of the {@code Message} interface
-   * whereas {@code getDefaultInstance()} is a static method of a specific
-   * class.  They return the same thing.
-   */
+  // (From MessageLite, re-declared here only for return type covariance.)
   Message getDefaultInstanceForType();
 
   /**
@@ -114,24 +112,6 @@
   /** Get the {@link UnknownFieldSet} for this message. */
   UnknownFieldSet getUnknownFields();
 
-  /**
-   * Returns true if all required fields in the message and all embedded
-   * messages are set, false otherwise.
-   */
-  boolean isInitialized();
-
-  /**
-   * Serializes the message and writes it to {@code output}.  This does not
-   * flush or close the stream.
-   */
-  void writeTo(CodedOutputStream output) throws IOException;
-
-  /**
-   * Get the number of bytes required to encode this message.  The result
-   * is only computed on the first call and memoized after that.
-   */
-  int getSerializedSize();
-
   // -----------------------------------------------------------------
   // Comparison and hashing
 
@@ -144,6 +124,7 @@
    * @param other object to be compared for equality with this message
    * @return <tt>true</tt> if the specified object is equal to this message
    */
+  @Override
   boolean equals(Object other);
 
   /**
@@ -154,6 +135,7 @@
    * @return the hash code value for this message
    * @see Map#hashCode()
    */
+  @Override
   int hashCode();
 
   // -----------------------------------------------------------------
@@ -163,67 +145,22 @@
    * Converts the message to a string in protocol buffer text format. This is
    * just a trivial wrapper around {@link TextFormat#printToString(Message)}.
    */
+  @Override
   String toString();
 
-  /**
-   * Serializes the message to a {@code ByteString} and returns it. This is
-   * just a trivial wrapper around
-   * {@link #writeTo(CodedOutputStream)}.
-   */
-  ByteString toByteString();
-
-  /**
-   * Serializes the message to a {@code byte} array and returns it.  This is
-   * just a trivial wrapper around
-   * {@link #writeTo(CodedOutputStream)}.
-   */
-  byte[] toByteArray();
-
-  /**
-   * Serializes the message and writes it to {@code output}.  This is just a
-   * trivial wrapper around {@link #writeTo(CodedOutputStream)}.  This does
-   * not flush or close the stream.
-   * <p>
-   * NOTE:  Protocol Buffers are not self-delimiting.  Therefore, if you write
-   * any more data to the stream after the message, you must somehow ensure
-   * that the parser on the receiving end does not interpret this as being
-   * part of the protocol message.  This can be done e.g. by writing the size
-   * of the message before the data, then making sure to limit the input to
-   * that size on the receiving end (e.g. by wrapping the InputStream in one
-   * which limits the input).  Alternatively, just use
-   * {@link #writeDelimitedTo(OutputStream)}.
-   */
-  void writeTo(OutputStream output) throws IOException;
-
-  /**
-   * Like {@link #writeTo(OutputStream)}, but writes the size of the message
-   * as a varint before writing the data.  This allows more data to be written
-   * to the stream after the message without the need to delimit the message
-   * data yourself.  Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
-   * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
-   * to parse messages written by this method.
-   */
-  void writeDelimitedTo(OutputStream output) throws IOException;
-
   // =================================================================
   // Builders
 
-  /**
-   * Constructs a new builder for a message of the same type as this message.
-   */
+  // (From MessageLite, re-declared here only for return type covariance.)
   Builder newBuilderForType();
-
-  /**
-   * Constructs a builder initialized with the current message.  Use this to
-   * derive a new message from the current one.
-   */
   Builder toBuilder();
 
   /**
    * Abstract interface implemented by Protocol Message builders.
    */
-  public static interface Builder extends Cloneable {
-    /** Resets all fields to their default values. */
+  interface Builder extends MessageLite.Builder {
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
     Builder clear();
 
     /**
@@ -244,71 +181,14 @@
      */
     Builder mergeFrom(Message other);
 
-    /**
-     * Construct the final message.  Once this is called, the Builder is no
-     * longer valid, and calling any other method may throw a
-     * NullPointerException.  If you need to continue working with the builder
-     * after calling {@code build()}, {@code clone()} it first.
-     * @throws UninitializedMessageException The message is missing one or more
-     *         required fields (i.e. {@link #isInitialized()} returns false).
-     *         Use {@link #buildPartial()} to bypass this check.
-     */
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
     Message build();
-
-    /**
-     * Like {@link #build()}, but does not throw an exception if the message
-     * is missing required fields.  Instead, a partial message is returned.
-     */
     Message buildPartial();
-
-    /**
-     * Clones the Builder.
-     * @see Object#clone()
-     */
     Builder clone();
-
-    /**
-     * Returns true if all required fields in the message and all embedded
-     * messages are set, false otherwise.
-     */
-    boolean isInitialized();
-
-    /**
-     * Parses a message of this type from the input and merges it with this
-     * message, as if using {@link Builder#mergeFrom(Message)}.
-     *
-     * <p>Warning:  This does not verify that all required fields are present in
-     * the input message.  If you call {@link #build()} without setting all
-     * required fields, it will throw an {@link UninitializedMessageException},
-     * which is a {@code RuntimeException} and thus might not be caught.  There
-     * are a few good ways to deal with this:
-     * <ul>
-     *   <li>Call {@link #isInitialized()} to verify that all required fields
-     *       are set before building.
-     *   <li>Parse the message separately using one of the static
-     *       {@code parseFrom} methods, then use {@link #mergeFrom(Message)}
-     *       to merge it with this one.  {@code parseFrom} will throw an
-     *       {@link InvalidProtocolBufferException} (an {@code IOException})
-     *       if some required fields are missing.
-     *   <li>Use {@code buildPartial()} to build, which ignores missing
-     *       required fields.
-     * </ul>
-     *
-     * <p>Note:  The caller should call
-     * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
-     * verify that the last tag seen was the appropriate end-group tag,
-     * or zero for EOF.
-     */
     Builder mergeFrom(CodedInputStream input) throws IOException;
-
-    /**
-     * Like {@link Builder#mergeFrom(CodedInputStream)}, but also
-     * parses extensions.  The extensions that you want to be able to parse
-     * must be registered in {@code extensionRegistry}.  Extensions not in
-     * the registry will be treated as unknown fields.
-     */
     Builder mergeFrom(CodedInputStream input,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws IOException;
 
     /**
@@ -317,10 +197,8 @@
      */
     Descriptors.Descriptor getDescriptorForType();
 
-    /**
-     * Get the message's type's default instance.
-     * See {@link Message#getDefaultInstanceForType()}.
-     */
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
     Message getDefaultInstanceForType();
 
     /**
@@ -399,92 +277,29 @@
     // ---------------------------------------------------------------
     // Convenience methods.
 
-    /**
-     * Parse {@code data} as a message of this type and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream)}.
-     */
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
     Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
-
-    /**
-     * Parse {@code data} as a message of this type and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
-     */
     Builder mergeFrom(ByteString data,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws InvalidProtocolBufferException;
-
-    /**
-     * Parse {@code data} as a message of this type and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream)}.
-     */
-    public Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
-
-    /**
-     * Parse {@code data} as a message of this type and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream)}.
-     */
-    public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
-
-    /**
-     * Parse {@code data} as a message of this type and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
-     */
+    Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+    Builder mergeFrom(byte[] data, int off, int len)
+                      throws InvalidProtocolBufferException;
     Builder mergeFrom(byte[] data,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws InvalidProtocolBufferException;
-
-    /**
-     * Parse {@code data} as a message of this type and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
-     */
     Builder mergeFrom(byte[] data, int off, int len,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws InvalidProtocolBufferException;
-
-    /**
-     * Parse a message of this type from {@code input} and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream)}.  Note that this method always
-     * reads the <i>entire</i> input (unless it throws an exception).  If you
-     * want it to stop earlier, you will need to wrap your input in some
-     * wrapper stream that limits reading.  Or, use
-     * {@link Message#writeDelimitedTo(OutputStream)} to write your message and
-     * {@link #mergeDelimitedFrom(InputStream)} to read it.
-     * <p>
-     * Despite usually reading the entire input, this does not close the stream.
-     */
     Builder mergeFrom(InputStream input) throws IOException;
-
-    /**
-     * Parse a message of this type from {@code input} and merge it with the
-     * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
-     */
     Builder mergeFrom(InputStream input,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws IOException;
-
-    /**
-     * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
-     * Instead, the size of the message (encoded as a varint) is read first,
-     * then the message data.  Use
-     * {@link Message#writeDelimitedTo(OutputStream)} to write messages in this
-     * format.
-     */
     Builder mergeDelimitedFrom(InputStream input)
                                throws IOException;
-
-    /**
-     * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
-     */
     Builder mergeDelimitedFrom(InputStream input,
-                               ExtensionRegistry extensionRegistry)
+                               ExtensionRegistryLite extensionRegistry)
                                throws IOException;
   }
 }
diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java
new file mode 100644
index 0000000..3001f36
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -0,0 +1,331 @@
+// 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.
+
+// TODO(kenton):  Use generics?  E.g. Builder<BuilderType extends Builder>, then
+//   mergeFrom*() could return BuilderType for better type-safety.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * <p>This interface is implemented by all protocol message objects.  Most
+ * users will be more interested in the Message interface, which is a subclass
+ * of MessageLite.  Use MessageLite instead when you only need the subset of
+ * features which it supports -- namely, nothing that uses descriptors or
+ * reflection.  You can instruct the protocol compiler to generate classes
+ * which implement only MessageLite, not the full Message interface, by adding
+ * the follow line to the .proto file:
+ * <pre>
+ *   option optimize_for = LITE_RUNTIME;
+ * </pre>
+ *
+ * <p>This is particularly useful on resource-constrained systems where the
+ * full protocol buffers runtime library is too big.
+ *
+ * <p>Note that on non-constrained systems (e.g. servers) when you need to link
+ * in lots of protocol definitions, a better way to reduce total code footprint
+ * is to use {@code optimize_for = CODE_SIZE}.  This will make the generated
+ * code smaller while still supporting all the same features (at the expense of
+ * speed).  {@code optimize_for = LITE_RUNTIME} is best when you only have a
+ * small number of message types linked into your binary, in which case the
+ * size of the protocol buffers runtime itself is the biggest problem.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface MessageLite {
+  /**
+   * Get an instance of the type with all fields set to their default values.
+   * This may or may not be a singleton.  This differs from the
+   * {@code getDefaultInstance()} method of generated message classes in that
+   * this method is an abstract method of the {@code MessageLite} interface
+   * whereas {@code getDefaultInstance()} is a static method of a specific
+   * class.  They return the same thing.
+   */
+  MessageLite getDefaultInstanceForType();
+
+  /**
+   * Returns true if all required fields in the message and all embedded
+   * messages are set, false otherwise.
+   */
+  boolean isInitialized();
+
+  /**
+   * Serializes the message and writes it to {@code output}.  This does not
+   * flush or close the stream.
+   */
+  void writeTo(CodedOutputStream output) throws IOException;
+
+  /**
+   * Get the number of bytes required to encode this message.  The result
+   * is only computed on the first call and memoized after that.
+   */
+  int getSerializedSize();
+
+  // -----------------------------------------------------------------
+  // Convenience methods.
+
+  /**
+   * Serializes the message to a {@code ByteString} and returns it. This is
+   * just a trivial wrapper around
+   * {@link #writeTo(CodedOutputStream)}.
+   */
+  ByteString toByteString();
+
+  /**
+   * Serializes the message to a {@code byte} array and returns it.  This is
+   * just a trivial wrapper around
+   * {@link #writeTo(CodedOutputStream)}.
+   */
+  byte[] toByteArray();
+
+  /**
+   * Serializes the message and writes it to {@code output}.  This is just a
+   * trivial wrapper around {@link #writeTo(CodedOutputStream)}.  This does
+   * not flush or close the stream.
+   * <p>
+   * NOTE:  Protocol Buffers are not self-delimiting.  Therefore, if you write
+   * any more data to the stream after the message, you must somehow ensure
+   * that the parser on the receiving end does not interpret this as being
+   * part of the protocol message.  This can be done e.g. by writing the size
+   * of the message before the data, then making sure to limit the input to
+   * that size on the receiving end (e.g. by wrapping the InputStream in one
+   * which limits the input).  Alternatively, just use
+   * {@link #writeDelimitedTo(OutputStream)}.
+   */
+  void writeTo(OutputStream output) throws IOException;
+
+  /**
+   * Like {@link #writeTo(OutputStream)}, but writes the size of the message
+   * as a varint before writing the data.  This allows more data to be written
+   * to the stream after the message without the need to delimit the message
+   * data yourself.  Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
+   * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
+   * to parse messages written by this method.
+   */
+  void writeDelimitedTo(OutputStream output) throws IOException;
+
+  // =================================================================
+  // Builders
+
+  /**
+   * Constructs a new builder for a message of the same type as this message.
+   */
+  Builder newBuilderForType();
+
+  /**
+   * Constructs a builder initialized with the current message.  Use this to
+   * derive a new message from the current one.
+   */
+  Builder toBuilder();
+
+  /**
+   * Abstract interface implemented by Protocol Message builders.
+   */
+  interface Builder extends Cloneable {
+    /** Resets all fields to their default values. */
+    Builder clear();
+
+    /**
+     * Construct the final message.  Once this is called, the Builder is no
+     * longer valid, and calling any other method will result in undefined
+     * behavior and may throw a NullPointerException.  If you need to continue
+     * working with the builder after calling {@code build()}, {@code clone()}
+     * it first.
+     * @throws UninitializedMessageException The message is missing one or more
+     *         required fields (i.e. {@link #isInitialized()} returns false).
+     *         Use {@link #buildPartial()} to bypass this check.
+     */
+    MessageLite build();
+
+    /**
+     * Like {@link #build()}, but does not throw an exception if the message
+     * is missing required fields.  Instead, a partial message is returned.
+     * Once this is called, the Builder is no longer valid, and calling any
+     * will result in undefined behavior and may throw a NullPointerException.
+     *
+     * If you need to continue working with the builder after calling
+     * {@code buildPartial()}, {@code clone()} it first.
+     */
+    MessageLite buildPartial();
+
+    /**
+     * Clones the Builder.
+     * @see Object#clone()
+     */
+    Builder clone();
+
+    /**
+     * Returns true if all required fields in the message and all embedded
+     * messages are set, false otherwise.
+     */
+    boolean isInitialized();
+
+    /**
+     * Parses a message of this type from the input and merges it with this
+     * message, as if using {@link Builder#mergeFrom(MessageLite)}.
+     *
+     * <p>Warning:  This does not verify that all required fields are present in
+     * the input message.  If you call {@link #build()} without setting all
+     * required fields, it will throw an {@link UninitializedMessageException},
+     * which is a {@code RuntimeException} and thus might not be caught.  There
+     * are a few good ways to deal with this:
+     * <ul>
+     *   <li>Call {@link #isInitialized()} to verify that all required fields
+     *       are set before building.
+     *   <li>Parse the message separately using one of the static
+     *       {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)}
+     *       to merge it with this one.  {@code parseFrom} will throw an
+     *       {@link InvalidProtocolBufferException} (an {@code IOException})
+     *       if some required fields are missing.
+     *   <li>Use {@code buildPartial()} to build, which ignores missing
+     *       required fields.
+     * </ul>
+     *
+     * <p>Note:  The caller should call
+     * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+     * verify that the last tag seen was the appropriate end-group tag,
+     * or zero for EOF.
+     */
+    Builder mergeFrom(CodedInputStream input) throws IOException;
+
+    /**
+     * Like {@link Builder#mergeFrom(CodedInputStream)}, but also
+     * parses extensions.  The extensions that you want to be able to parse
+     * must be registered in {@code extensionRegistry}.  Extensions not in
+     * the registry will be treated as unknown fields.
+     */
+    Builder mergeFrom(CodedInputStream input,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws IOException;
+
+    /**
+     * Get the message's type's default instance.
+     * See {@link MessageLite#getDefaultInstanceForType()}.
+     */
+    MessageLite getDefaultInstanceForType();
+
+    // ---------------------------------------------------------------
+    // Convenience methods.
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     */
+    Builder mergeFrom(ByteString data,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    Builder mergeFrom(byte[] data, int off, int len)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     */
+    Builder mergeFrom(byte[] data,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     */
+    Builder mergeFrom(byte[] data, int off, int len,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse a message of this type from {@code input} and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.  Note that this method always
+     * reads the <i>entire</i> input (unless it throws an exception).  If you
+     * want it to stop earlier, you will need to wrap your input in some
+     * wrapper stream that limits reading.  Or, use
+     * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message
+     * and {@link #mergeDelimitedFrom(InputStream)} to read it.
+     * <p>
+     * Despite usually reading the entire input, this does not close the stream.
+     */
+    Builder mergeFrom(InputStream input) throws IOException;
+
+    /**
+     * Parse a message of this type from {@code input} and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     */
+    Builder mergeFrom(InputStream input,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws IOException;
+
+    /**
+     * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
+     * Instead, the size of the message (encoded as a varint) is read first,
+     * then the message data.  Use
+     * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
+     * this format.
+     */
+    Builder mergeDelimitedFrom(InputStream input)
+                               throws IOException;
+
+    /**
+     * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
+     */
+    Builder mergeDelimitedFrom(InputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+                               throws IOException;
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
index 8efca8a..112400f 100644
--- a/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
+++ b/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
@@ -37,7 +37,7 @@
  * Interface of useful methods added to all enums generated by the protocol
  * compiler.
  */
-public interface ProtocolMessageEnum {
+public interface ProtocolMessageEnum extends Internal.EnumLite {
 
   /**
    * Return the value's numeric value as defined in the .proto file.
diff --git a/java/src/main/java/com/google/protobuf/RpcUtil.java b/java/src/main/java/com/google/protobuf/RpcUtil.java
index 8144bbf..b1b959a 100644
--- a/java/src/main/java/com/google/protobuf/RpcUtil.java
+++ b/java/src/main/java/com/google/protobuf/RpcUtil.java
@@ -71,11 +71,11 @@
       final Class<Type> originalClass,
       final Type defaultInstance) {
     return new RpcCallback<Message>() {
-      public void run(Message parameter) {
+      public void run(final Message parameter) {
         Type typedParameter;
         try {
           typedParameter = originalClass.cast(parameter);
-        } catch (ClassCastException e) {
+        } catch (ClassCastException ignored) {
           typedParameter = copyAsType(defaultInstance, parameter);
         }
         originalCallback.run(typedParameter);
@@ -90,7 +90,7 @@
    */
   @SuppressWarnings("unchecked")
   private static <Type extends Message> Type copyAsType(
-      Type typeDefaultInstance, Message source) {
+      final Type typeDefaultInstance, final Message source) {
     return (Type)typeDefaultInstance.newBuilderForType()
                                     .mergeFrom(source)
                                     .build();
@@ -106,8 +106,9 @@
     RpcCallback<ParameterType> newOneTimeCallback(
       final RpcCallback<ParameterType> originalCallback) {
     return new RpcCallback<ParameterType>() {
-      boolean alreadyCalled = false;
-      public void run(ParameterType parameter) {
+      private boolean alreadyCalled = false;
+
+      public void run(final ParameterType parameter) {
         synchronized(this) {
           if (alreadyCalled) {
             throw new AlreadyCalledException();
@@ -124,6 +125,8 @@
    * Exception thrown when a one-time callback is called more than once.
    */
   public static final class AlreadyCalledException extends RuntimeException {
+    private static final long serialVersionUID = 5469741279507848266L;
+
     public AlreadyCalledException() {
       super("This RpcCallback was already called and cannot be called " +
             "multiple times.");
diff --git a/java/src/main/java/com/google/protobuf/ServiceException.java b/java/src/main/java/com/google/protobuf/ServiceException.java
index 70b9d0c..c043a77 100644
--- a/java/src/main/java/com/google/protobuf/ServiceException.java
+++ b/java/src/main/java/com/google/protobuf/ServiceException.java
@@ -32,11 +32,13 @@
 
 /**
  * Thrown by blocking RPC methods when a failure occurs.
- * 
+ *
  * @author cpovirk@google.com (Chris Povirk)
  */
 public final class ServiceException extends Exception {
-  public ServiceException(String message) {
+  private static final long serialVersionUID = -1219262335729891920L;
+
+  public ServiceException(final String message) {
     super(message);
   }
 }
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 3dcf68c..a855720 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -52,22 +52,25 @@
  * @author kenton@google.com Kenton Varda
  */
 public final class TextFormat {
+  private TextFormat() {
+  }
 
   /**
    * Outputs a textual representation of the Protocol Message supplied into
    * the parameter output. (This representation is the new version of the
    * classic "ProtocolPrinter" output from the original Protocol Buffer system)
    */
-  public static void print(Message message, Appendable output)
+  public static void print(final Message message, final Appendable output)
                            throws IOException {
-    TextGenerator generator = new TextGenerator(output);
+    final TextGenerator generator = new TextGenerator(output);
     print(message, generator);
   }
 
   /** Outputs a textual representation of {@code fields} to {@code output}. */
-  public static void print(UnknownFieldSet fields, Appendable output)
+  public static void print(final UnknownFieldSet fields,
+                           final Appendable output)
                            throws IOException {
-    TextGenerator generator = new TextGenerator(output);
+    final TextGenerator generator = new TextGenerator(output);
     printUnknownFields(fields, generator);
   }
 
@@ -75,9 +78,9 @@
    * Like {@code print()}, but writes directly to a {@code String} and
    * returns it.
    */
-  public static String printToString(Message message) {
+  public static String printToString(final Message message) {
     try {
-      StringBuilder text = new StringBuilder();
+      final StringBuilder text = new StringBuilder();
       print(message, text);
       return text.toString();
     } catch (IOException e) {
@@ -91,9 +94,9 @@
    * Like {@code print()}, but writes directly to a {@code String} and
    * returns it.
    */
-  public static String printToString(UnknownFieldSet fields) {
+  public static String printToString(final UnknownFieldSet fields) {
     try {
-      StringBuilder text = new StringBuilder();
+      final StringBuilder text = new StringBuilder();
       print(fields, text);
       return text.toString();
     } catch (IOException e) {
@@ -103,22 +106,44 @@
     }
   }
 
-  private static void print(Message message, TextGenerator generator)
+  private static void print(final Message message,
+                            final TextGenerator generator)
       throws IOException {
-    for (Map.Entry<FieldDescriptor, Object> field :
+    for (final Map.Entry<FieldDescriptor, Object> field :
          message.getAllFields().entrySet()) {
       printField(field.getKey(), field.getValue(), generator);
     }
     printUnknownFields(message.getUnknownFields(), generator);
   }
+  
+  public static void printField(final FieldDescriptor field,
+                                final Object value,
+                                final Appendable output)
+                                throws IOException {
+    final TextGenerator generator = new TextGenerator(output);
+    printField(field, value, generator);
+  }
 
-  public static void printField(FieldDescriptor field,
-                                Object value,
-                                TextGenerator generator)
+  public static String printFieldToString(final FieldDescriptor field,
+                                          final Object value) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      printField(field, value, text);
+      return text.toString();
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Writing to a StringBuilder threw an IOException (should never " +
+        "happen).", e);  
+    }
+  }
+  
+  private static void printField(final FieldDescriptor field,
+                                final Object value,
+                                final TextGenerator generator)
                                 throws IOException {
     if (field.isRepeated()) {
       // Repeated field.  Print each element.
-      for (Object element : (List) value) {
+      for (final Object element : (List) value) {
         printSingleField(field, element, generator);
       }
     } else {
@@ -126,9 +151,9 @@
     }
   }
 
-  private static void printSingleField(FieldDescriptor field,
-                                       Object value,
-                                       TextGenerator generator)
+  private static void printSingleField(final FieldDescriptor field,
+                                       final Object value,
+                                       final TextGenerator generator)
                                        throws IOException {
     if (field.isExtension()) {
       generator.print("[");
@@ -168,9 +193,9 @@
     generator.print("\n");
   }
 
-  private static void printFieldValue(FieldDescriptor field,
-                                      Object value,
-                                      TextGenerator generator)
+  private static void printFieldValue(final FieldDescriptor field,
+                                      final Object value,
+                                      final TextGenerator generator)
                                       throws IOException {
     switch (field.getType()) {
       case INT32:
@@ -202,17 +227,15 @@
         generator.print("\"");
         break;
 
-      case BYTES: {
+      case BYTES:
         generator.print("\"");
         generator.print(escapeBytes((ByteString) value));
         generator.print("\"");
         break;
-      }
 
-      case ENUM: {
+      case ENUM:
         generator.print(((EnumValueDescriptor) value).getName());
         break;
-      }
 
       case MESSAGE:
       case GROUP:
@@ -221,39 +244,39 @@
     }
   }
 
-  private static void printUnknownFields(UnknownFieldSet unknownFields,
-                                         TextGenerator generator)
+  private static void printUnknownFields(final UnknownFieldSet unknownFields,
+                                         final TextGenerator generator)
                                          throws IOException {
-    for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+    for (final Map.Entry<Integer, UnknownFieldSet.Field> entry :
          unknownFields.asMap().entrySet()) {
-      String prefix = entry.getKey().toString() + ": ";
-      UnknownFieldSet.Field field = entry.getValue();
+      final String prefix = entry.getKey().toString() + ": ";
+      final UnknownFieldSet.Field field = entry.getValue();
 
-      for (long value : field.getVarintList()) {
+      for (final long value : field.getVarintList()) {
         generator.print(entry.getKey().toString());
         generator.print(": ");
         generator.print(unsignedToString(value));
         generator.print("\n");
       }
-      for (int value : field.getFixed32List()) {
+      for (final int value : field.getFixed32List()) {
         generator.print(entry.getKey().toString());
         generator.print(": ");
         generator.print(String.format((Locale) null, "0x%08x", value));
         generator.print("\n");
       }
-      for (long value : field.getFixed64List()) {
+      for (final long value : field.getFixed64List()) {
         generator.print(entry.getKey().toString());
         generator.print(": ");
         generator.print(String.format((Locale) null, "0x%016x", value));
         generator.print("\n");
       }
-      for (ByteString value : field.getLengthDelimitedList()) {
+      for (final ByteString value : field.getLengthDelimitedList()) {
         generator.print(entry.getKey().toString());
         generator.print(": \"");
         generator.print(escapeBytes(value));
         generator.print("\"\n");
       }
-      for (UnknownFieldSet value : field.getGroupList()) {
+      for (final UnknownFieldSet value : field.getGroupList()) {
         generator.print(entry.getKey().toString());
         generator.print(" {\n");
         generator.indent();
@@ -265,7 +288,7 @@
   }
 
   /** Convert an unsigned 32-bit integer to a string. */
-  private static String unsignedToString(int value) {
+  private static String unsignedToString(final int value) {
     if (value >= 0) {
       return Integer.toString(value);
     } else {
@@ -274,7 +297,7 @@
   }
 
   /** Convert an unsigned 64-bit integer to a string. */
-  private static String unsignedToString(long value) {
+  private static String unsignedToString(final long value) {
     if (value >= 0) {
       return Long.toString(value);
     } else {
@@ -288,13 +311,12 @@
   /**
    * An inner class for writing text to the output stream.
    */
-  static private final class TextGenerator {
+  private static final class TextGenerator {
+    private Appendable output;
+    private boolean atStartOfLine = true;
+    private final StringBuilder indent = new StringBuilder();
 
-    Appendable output;
-    boolean atStartOfLine = true;
-    StringBuilder indent = new StringBuilder();
-
-    public TextGenerator(Appendable output) {
+    private TextGenerator(final Appendable output) {
       this.output = output;
     }
 
@@ -312,7 +334,7 @@
      * level is zero.
      */
     public void outdent() {
-      int length = indent.length();
+      final int length = indent.length();
       if (length == 0) {
         throw new IllegalArgumentException(
             " Outdent() without matching Indent().");
@@ -323,8 +345,8 @@
     /**
      * Print text to the output stream.
      */
-    public void print(CharSequence text) throws IOException {
-      int size = text.length();
+    public void print(final CharSequence text) throws IOException {
+      final int size = text.length();
       int pos = 0;
 
       for (int i = 0; i < size; i++) {
@@ -337,7 +359,8 @@
       write(text.subSequence(pos, size), size - pos);
     }
 
-    private void write(CharSequence data, int size) throws IOException {
+    private void write(final CharSequence data, final int size)
+                       throws IOException {
       if (size == 0) {
         return;
       }
@@ -399,27 +422,27 @@
 
     // We use possesive quantifiers (*+ and ++) because otherwise the Java
     // regex matcher has stack overflows on large inputs.
-    private static Pattern WHITESPACE =
+    private static final Pattern WHITESPACE =
       Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
-    private static Pattern TOKEN = Pattern.compile(
+    private static final Pattern TOKEN = Pattern.compile(
       "[a-zA-Z_][0-9a-zA-Z_+-]*+|" +                // an identifier
       "[0-9+-][0-9a-zA-Z_.+-]*+|" +                 // a number
       "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" +       // a double-quoted string
       "\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)",         // a single-quoted string
       Pattern.MULTILINE);
 
-    private static Pattern DOUBLE_INFINITY = Pattern.compile(
+    private static final Pattern DOUBLE_INFINITY = Pattern.compile(
       "-?inf(inity)?",
       Pattern.CASE_INSENSITIVE);
-    private static Pattern FLOAT_INFINITY = Pattern.compile(
+    private static final Pattern FLOAT_INFINITY = Pattern.compile(
       "-?inf(inity)?f?",
       Pattern.CASE_INSENSITIVE);
-    private static Pattern FLOAT_NAN = Pattern.compile(
+    private static final Pattern FLOAT_NAN = Pattern.compile(
       "nanf?",
       Pattern.CASE_INSENSITIVE);
 
     /** Construct a tokenizer that parses tokens from the given text. */
-    public Tokenizer(CharSequence text) {
+    private Tokenizer(final CharSequence text) {
       this.text = text;
       this.matcher = WHITESPACE.matcher(text);
       skipWhitespace();
@@ -481,7 +504,7 @@
      * If the next token exactly matches {@code token}, consume it and return
      * {@code true}.  Otherwise, return {@code false} without doing anything.
      */
-    public boolean tryConsume(String token) {
+    public boolean tryConsume(final String token) {
       if (currentToken.equals(token)) {
         nextToken();
         return true;
@@ -494,7 +517,7 @@
      * If the next token exactly matches {@code token}, consume it.  Otherwise,
      * throw a {@link ParseException}.
      */
-    public void consume(String token) throws ParseException {
+    public void consume(final String token) throws ParseException {
       if (!tryConsume(token)) {
         throw parseException("Expected \"" + token + "\".");
       }
@@ -509,7 +532,7 @@
         return false;
       }
 
-      char c = currentToken.charAt(0);
+      final char c = currentToken.charAt(0);
       return ('0' <= c && c <= '9') ||
              c == '-' || c == '+';
     }
@@ -520,7 +543,7 @@
      */
     public String consumeIdentifier() throws ParseException {
       for (int i = 0; i < currentToken.length(); i++) {
-        char c = currentToken.charAt(i);
+        final char c = currentToken.charAt(i);
         if (('a' <= c && c <= 'z') ||
             ('A' <= c && c <= 'Z') ||
             ('0' <= c && c <= '9') ||
@@ -531,7 +554,7 @@
         }
       }
 
-      String result = currentToken;
+      final String result = currentToken;
       nextToken();
       return result;
     }
@@ -542,7 +565,7 @@
      */
     public int consumeInt32() throws ParseException {
       try {
-        int result = parseInt32(currentToken);
+        final int result = parseInt32(currentToken);
         nextToken();
         return result;
       } catch (NumberFormatException e) {
@@ -556,7 +579,7 @@
      */
     public int consumeUInt32() throws ParseException {
       try {
-        int result = parseUInt32(currentToken);
+        final int result = parseUInt32(currentToken);
         nextToken();
         return result;
       } catch (NumberFormatException e) {
@@ -570,7 +593,7 @@
      */
     public long consumeInt64() throws ParseException {
       try {
-        long result = parseInt64(currentToken);
+        final long result = parseInt64(currentToken);
         nextToken();
         return result;
       } catch (NumberFormatException e) {
@@ -584,7 +607,7 @@
      */
     public long consumeUInt64() throws ParseException {
       try {
-        long result = parseUInt64(currentToken);
+        final long result = parseUInt64(currentToken);
         nextToken();
         return result;
       } catch (NumberFormatException e) {
@@ -600,7 +623,7 @@
       // We need to parse infinity and nan separately because
       // Double.parseDouble() does not accept "inf", "infinity", or "nan".
       if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
-        boolean negative = currentToken.startsWith("-");
+        final boolean negative = currentToken.startsWith("-");
         nextToken();
         return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
       }
@@ -609,7 +632,7 @@
         return Double.NaN;
       }
       try {
-        double result = Double.parseDouble(currentToken);
+        final double result = Double.parseDouble(currentToken);
         nextToken();
         return result;
       } catch (NumberFormatException e) {
@@ -625,7 +648,7 @@
       // We need to parse infinity and nan separately because
       // Float.parseFloat() does not accept "inf", "infinity", or "nan".
       if (FLOAT_INFINITY.matcher(currentToken).matches()) {
-        boolean negative = currentToken.startsWith("-");
+        final boolean negative = currentToken.startsWith("-");
         nextToken();
         return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
       }
@@ -634,7 +657,7 @@
         return Float.NaN;
       }
       try {
-        float result = Float.parseFloat(currentToken);
+        final float result = Float.parseFloat(currentToken);
         nextToken();
         return result;
       } catch (NumberFormatException e) {
@@ -672,7 +695,8 @@
      * {@link ParseException}.
      */
     public ByteString consumeByteString() throws ParseException {
-      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.");
       }
@@ -683,11 +707,12 @@
       }
 
       try {
-        String escaped = currentToken.substring(1, currentToken.length() - 1);
-        ByteString result = unescapeBytes(escaped);
+        final String escaped =
+            currentToken.substring(1, currentToken.length() - 1);
+        final ByteString result = unescapeBytes(escaped);
         nextToken();
         return result;
-      } catch (InvalidEscapeSequence e) {
+      } catch (InvalidEscapeSequenceException e) {
         throw parseException(e.getMessage());
       }
     }
@@ -696,7 +721,7 @@
      * Returns a {@link ParseException} with the current line and column
      * numbers in the description, suitable for throwing.
      */
-    public ParseException parseException(String description) {
+    public ParseException parseException(final String description) {
       // Note:  People generally prefer one-based line and column numbers.
       return new ParseException(
         (line + 1) + ":" + (column + 1) + ": " + description);
@@ -706,7 +731,8 @@
      * Returns a {@link ParseException} with the line and column numbers of
      * the previous token in the description, suitable for throwing.
      */
-    public ParseException parseExceptionPreviousToken(String description) {
+    public ParseException parseExceptionPreviousToken(
+        final String description) {
       // Note:  People generally prefer one-based line and column numbers.
       return new ParseException(
         (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
@@ -716,7 +742,8 @@
      * Constructs an appropriate {@link ParseException} for the given
      * {@code NumberFormatException} when trying to parse an integer.
      */
-    private ParseException integerParseException(NumberFormatException e) {
+    private ParseException integerParseException(
+        final NumberFormatException e) {
       return parseException("Couldn't parse integer: " + e.getMessage());
     }
 
@@ -724,14 +751,16 @@
      * Constructs an appropriate {@link ParseException} for the given
      * {@code NumberFormatException} when trying to parse a float or double.
      */
-    private ParseException floatParseException(NumberFormatException e) {
+    private ParseException floatParseException(final NumberFormatException e) {
       return parseException("Couldn't parse number: " + e.getMessage());
     }
   }
 
   /** Thrown when parsing an invalid text format message. */
   public static class ParseException extends IOException {
-    public ParseException(String message) {
+    private static final long serialVersionUID = 3196188060225107702L;
+
+    public ParseException(final String message) {
       super(message);
     }
   }
@@ -740,9 +769,9 @@
    * Parse a text-format message from {@code input} and merge the contents
    * into {@code builder}.
    */
-  public static void merge(Readable input,
-                           Message.Builder builder)
-                           throws ParseException, IOException {
+  public static void merge(final Readable input,
+                           final Message.Builder builder)
+                           throws IOException {
     merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
   }
 
@@ -750,8 +779,8 @@
    * Parse a text-format message from {@code input} and merge the contents
    * into {@code builder}.
    */
-  public static void merge(CharSequence input,
-                           Message.Builder builder)
+  public static void merge(final CharSequence input,
+                           final Message.Builder builder)
                            throws ParseException {
     merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
   }
@@ -761,10 +790,10 @@
    * into {@code builder}.  Extensions will be recognized if they are
    * registered in {@code extensionRegistry}.
    */
-  public static void merge(Readable input,
-                           ExtensionRegistry extensionRegistry,
-                           Message.Builder builder)
-                           throws ParseException, IOException {
+  public static void merge(final Readable input,
+                           final ExtensionRegistry extensionRegistry,
+                           final Message.Builder builder)
+                           throws IOException {
     // Read the entire input to a String then parse that.
 
     // If StreamTokenizer were not quite so crippled, or if there were a kind
@@ -780,12 +809,12 @@
 
   // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
   // overhead is worthwhile
-  private static StringBuilder toStringBuilder(Readable input)
+  private static StringBuilder toStringBuilder(final Readable input)
       throws IOException {
-    StringBuilder text = new StringBuilder();
-    CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
+    final StringBuilder text = new StringBuilder();
+    final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
     while (true) {
-      int n = input.read(buffer);
+      final int n = input.read(buffer);
       if (n == -1) {
         break;
       }
@@ -800,11 +829,11 @@
    * into {@code builder}.  Extensions will be recognized if they are
    * registered in {@code extensionRegistry}.
    */
-  public static void merge(CharSequence input,
-                           ExtensionRegistry extensionRegistry,
-                           Message.Builder builder)
+  public static void merge(final CharSequence input,
+                           final ExtensionRegistry extensionRegistry,
+                           final Message.Builder builder)
                            throws ParseException {
-    Tokenizer tokenizer = new Tokenizer(input);
+    final Tokenizer tokenizer = new Tokenizer(input);
 
     while (!tokenizer.atEnd()) {
       mergeField(tokenizer, extensionRegistry, builder);
@@ -815,19 +844,20 @@
    * Parse a single field from {@code tokenizer} and merge it into
    * {@code builder}.
    */
-  private static void mergeField(Tokenizer tokenizer,
-                                 ExtensionRegistry extensionRegistry,
-                                 Message.Builder builder)
+  private static void mergeField(final Tokenizer tokenizer,
+                                 final ExtensionRegistry extensionRegistry,
+                                 final Message.Builder builder)
                                  throws ParseException {
     FieldDescriptor field;
-    Descriptor type = builder.getDescriptorForType();
+    final Descriptor type = builder.getDescriptorForType();
     ExtensionRegistry.ExtensionInfo extension = null;
 
     if (tokenizer.tryConsume("[")) {
       // An extension.
-      StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier());
+      final StringBuilder name =
+          new StringBuilder(tokenizer.consumeIdentifier());
       while (tokenizer.tryConsume(".")) {
-        name.append(".");
+        name.append('.');
         name.append(tokenizer.consumeIdentifier());
       }
 
@@ -846,7 +876,7 @@
 
       field = extension.descriptor;
     } else {
-      String name = tokenizer.consumeIdentifier();
+      final String name = tokenizer.consumeIdentifier();
       field = type.findFieldByName(name);
 
       // Group names are expected to be capitalized as they appear in the
@@ -855,7 +885,7 @@
       if (field == null) {
         // Explicitly specify US locale so that this code does not break when
         // executing in Turkey.
-        String lowerName = name.toLowerCase(Locale.US);
+        final String lowerName = name.toLowerCase(Locale.US);
         field = type.findFieldByName(lowerName);
         // If the case-insensitive match worked but the field is NOT a group,
         if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
@@ -880,7 +910,7 @@
     if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
       tokenizer.tryConsume(":");  // optional
 
-      String endToken;
+      final String endToken;
       if (tokenizer.tryConsume("<")) {
         endToken = ">";
       } else {
@@ -888,7 +918,7 @@
         endToken = "}";
       }
 
-      Message.Builder subBuilder;
+      final Message.Builder subBuilder;
       if (extension == null) {
         subBuilder = builder.newBuilderForField(field);
       } else {
@@ -951,19 +981,19 @@
           value = tokenizer.consumeByteString();
           break;
 
-        case ENUM: {
-          EnumDescriptor enumType = field.getEnumType();
+        case ENUM:
+          final EnumDescriptor enumType = field.getEnumType();
 
           if (tokenizer.lookingAtInteger()) {
-            int number = tokenizer.consumeInt32();
+            final int number = tokenizer.consumeInt32();
             value = enumType.findValueByNumber(number);
             if (value == null) {
               throw tokenizer.parseExceptionPreviousToken(
                 "Enum type \"" + enumType.getFullName() +
-                "\" has no value with number " + number + ".");
+                "\" has no value with number " + number + '.');
             }
           } else {
-            String id = tokenizer.consumeIdentifier();
+            final String id = tokenizer.consumeIdentifier();
             value = enumType.findValueByName(id);
             if (value == null) {
               throw tokenizer.parseExceptionPreviousToken(
@@ -973,7 +1003,6 @@
           }
 
           break;
-        }
 
         case MESSAGE:
         case GROUP:
@@ -1002,10 +1031,10 @@
    * which no defined short-hand escape sequence is defined will be escaped
    * using 3-digit octal sequences.
    */
-  static String escapeBytes(ByteString input) {
-    StringBuilder builder = new StringBuilder(input.size());
+  static String escapeBytes(final ByteString input) {
+    final StringBuilder builder = new StringBuilder(input.size());
     for (int i = 0; i < input.size(); i++) {
-      byte b = input.byteAt(i);
+      final byte b = input.byteAt(i);
       switch (b) {
         // Java does not recognize \a or \v, apparently.
         case 0x07: builder.append("\\a" ); break;
@@ -1038,9 +1067,9 @@
    * {@link #escapeBytes(ByteString)}.  Two-digit hex escapes (starting with
    * "\x") are also recognized.
    */
-  static ByteString unescapeBytes(CharSequence input)
-      throws InvalidEscapeSequence {
-    byte[] result = new byte[input.length()];
+  static ByteString unescapeBytes(final CharSequence input)
+      throws InvalidEscapeSequenceException {
+    final byte[] result = new byte[input.length()];
     int pos = 0;
     for (int i = 0; i < input.length(); i++) {
       char c = input.charAt(i);
@@ -1080,7 +1109,7 @@
                   ++i;
                   code = digitValue(input.charAt(i));
                 } else {
-                  throw new InvalidEscapeSequence(
+                  throw new InvalidEscapeSequenceException(
                     "Invalid escape sequence: '\\x' with no digits");
                 }
                 if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
@@ -1091,12 +1120,12 @@
                 break;
 
               default:
-                throw new InvalidEscapeSequence(
-                  "Invalid escape sequence: '\\" + c + "'");
+                throw new InvalidEscapeSequenceException(
+                  "Invalid escape sequence: '\\" + c + '\'');
             }
           }
         } else {
-          throw new InvalidEscapeSequence(
+          throw new InvalidEscapeSequenceException(
             "Invalid escape sequence: '\\' at end of string.");
         }
       } else {
@@ -1111,8 +1140,10 @@
    * Thrown by {@link TextFormat#unescapeBytes} and
    * {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
    */
-  static class InvalidEscapeSequence extends IOException {
-    public InvalidEscapeSequence(String description) {
+  static class InvalidEscapeSequenceException extends IOException {
+    private static final long serialVersionUID = -8164033650142593304L;
+
+    InvalidEscapeSequenceException(final String description) {
       super(description);
     }
   }
@@ -1122,7 +1153,7 @@
    * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
    * individually as a 3-digit octal escape.  Yes, it's weird.
    */
-  static String escapeText(String input) {
+  static String escapeText(final String input) {
     return escapeBytes(ByteString.copyFromUtf8(input));
   }
 
@@ -1130,17 +1161,18 @@
    * Un-escape a text string as escaped using {@link #escapeText(String)}.
    * Two-digit hex escapes (starting with "\x") are also recognized.
    */
-  static String unescapeText(String input) throws InvalidEscapeSequence {
+  static String unescapeText(final String input)
+                             throws InvalidEscapeSequenceException {
     return unescapeBytes(input).toStringUtf8();
   }
 
   /** Is this an octal digit? */
-  private static boolean isOctal(char c) {
+  private static boolean isOctal(final char c) {
     return '0' <= c && c <= '7';
   }
 
   /** Is this a hex digit? */
-  private static boolean isHex(char c) {
+  private static boolean isHex(final char c) {
     return ('0' <= c && c <= '9') ||
            ('a' <= c && c <= 'f') ||
            ('A' <= c && c <= 'F');
@@ -1151,7 +1183,7 @@
    * numeric value.  This is like {@code Character.digit()} but we don't accept
    * non-ASCII digits.
    */
-  private static int digitValue(char c) {
+  private static int digitValue(final char c) {
     if ('0' <= c && c <= '9') {
       return c - '0';
     } else if ('a' <= c && c <= 'z') {
@@ -1166,7 +1198,7 @@
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
    * and "0" to signify hexidecimal and octal numbers, respectively.
    */
-  static int parseInt32(String text) throws NumberFormatException {
+  static int parseInt32(final String text) throws NumberFormatException {
     return (int) parseInteger(text, true, false);
   }
 
@@ -1177,7 +1209,7 @@
    * result is coerced to a (signed) {@code int} when returned since Java has
    * no unsigned integer type.
    */
-  static int parseUInt32(String text) throws NumberFormatException {
+  static int parseUInt32(final String text) throws NumberFormatException {
     return (int) parseInteger(text, false, false);
   }
 
@@ -1186,7 +1218,7 @@
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
    * and "0" to signify hexidecimal and octal numbers, respectively.
    */
-  static long parseInt64(String text) throws NumberFormatException {
+  static long parseInt64(final String text) throws NumberFormatException {
     return parseInteger(text, true, true);
   }
 
@@ -1197,13 +1229,13 @@
    * result is coerced to a (signed) {@code long} when returned since Java has
    * no unsigned long type.
    */
-  static long parseUInt64(String text) throws NumberFormatException {
+  static long parseUInt64(final String text) throws NumberFormatException {
     return parseInteger(text, false, true);
   }
 
-  private static long parseInteger(String text,
-                                   boolean isSigned,
-                                   boolean isLong)
+  private static long parseInteger(final String text,
+                                   final boolean isSigned,
+                                   final boolean isLong)
                                    throws NumberFormatException {
     int pos = 0;
 
@@ -1224,7 +1256,7 @@
       radix = 8;
     }
 
-    String numberText = text.substring(pos);
+    final String numberText = text.substring(pos);
 
     long result = 0;
     if (numberText.length() < 16) {
diff --git a/java/src/main/java/com/google/protobuf/UninitializedMessageException.java b/java/src/main/java/com/google/protobuf/UninitializedMessageException.java
index a1032ca..8743c12 100644
--- a/java/src/main/java/com/google/protobuf/UninitializedMessageException.java
+++ b/java/src/main/java/com/google/protobuf/UninitializedMessageException.java
@@ -30,12 +30,8 @@
 
 package com.google.protobuf;
 
-import com.google.protobuf.Descriptors.FieldDescriptor;
-
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 /**
  * Thrown when attempting to build a protocol message that is missing required
@@ -51,11 +47,15 @@
  * @author kenton@google.com Kenton Varda
  */
 public class UninitializedMessageException extends RuntimeException {
-  public UninitializedMessageException(Message message) {
-    this(findMissingFields(message));
+  private static final long serialVersionUID = -7466929953374883507L;
+
+  public UninitializedMessageException(final MessageLite message) {
+    super("Message was missing required fields.  (Lite runtime could not " +
+          "determine which fields were missing).");
+    missingFields = null;
   }
 
-  private UninitializedMessageException(List<String> missingFields) {
+  public UninitializedMessageException(final List<String> missingFields) {
     super(buildDescription(missingFields));
     this.missingFields = missingFields;
   }
@@ -65,6 +65,8 @@
   /**
    * Get a list of human-readable names of required fields missing from this
    * message.  Each name is a full path to a field, e.g. "foo.bar[5].baz".
+   * Returns null if the lite runtime was used, since it lacks the ability to
+   * find missing fields.
    */
   public List<String> getMissingFields() {
     return Collections.unmodifiableList(missingFields);
@@ -80,11 +82,11 @@
   }
 
   /** Construct the description string for this exception. */
-  private static String buildDescription(List<String> missingFields) {
-    StringBuilder description =
+  private static String buildDescription(final List<String> missingFields) {
+    final StringBuilder description =
       new StringBuilder("Message missing required fields: ");
     boolean first = true;
-    for (String field : missingFields) {
+    for (final String field : missingFields) {
       if (first) {
         first = false;
       } else {
@@ -94,67 +96,4 @@
     }
     return description.toString();
   }
-
-  /**
-   * Populates {@code this.missingFields} with the full "path" of each
-   * missing required field in the given message.
-   */
-  private static List<String> findMissingFields(Message message) {
-    List<String> results = new ArrayList<String>();
-    findMissingFields(message, "", results);
-    return results;
-  }
-
-  /** Recursive helper implementing {@link #findMissingFields(Message)}. */
-  private static void findMissingFields(Message message, String prefix,
-                                        List<String> results) {
-    for (FieldDescriptor field : message.getDescriptorForType().getFields()) {
-      if (field.isRequired() && !message.hasField(field)) {
-        results.add(prefix + field.getName());
-      }
-    }
-
-    for (Map.Entry<FieldDescriptor, Object> entry :
-         message.getAllFields().entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      Object value = entry.getValue();
-
-      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        if (field.isRepeated()) {
-          int i = 0;
-          for (Object element : (List) value) {
-            findMissingFields((Message) element,
-                              subMessagePrefix(prefix, field, i++),
-                              results);
-          }
-        } else {
-          if (message.hasField(field)) {
-            findMissingFields((Message) value,
-                              subMessagePrefix(prefix, field, -1),
-                              results);
-          }
-        }
-      }
-    }
-  }
-
-  private static String subMessagePrefix(String prefix,
-                                         FieldDescriptor field,
-                                         int index) {
-    StringBuilder result = new StringBuilder(prefix);
-    if (field.isExtension()) {
-      result.append('(')
-            .append(field.getFullName())
-            .append(')');
-    } else {
-      result.append(field.getName());
-    }
-    if (index != -1) {
-      result.append('[')
-            .append(index)
-            .append(']');
-    }
-    result.append('.');
-    return result.toString();
-  }
 }
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 77fef32..239c2ac 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -30,15 +30,17 @@
 
 package com.google.protobuf;
 
-import java.io.InputStream;
+import com.google.protobuf.Internal.ThreadLocalQuickQueue;
+
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * {@code UnknownFieldSet} is used to keep track of fields which were seen when
@@ -48,56 +50,59 @@
  * compiled before the new types were added.
  *
  * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
- * {@link Message.Builder} contains an {@link UnknownFieldSet.Builder}).
+ * {@link Message.Builder} contains an {@link Builder}).
  *
  * <p>Most users will never need to use this class.
  *
  * @author kenton@google.com Kenton Varda
  */
-public final class UnknownFieldSet {
+public final class UnknownFieldSet implements MessageLite {
   private UnknownFieldSet() {}
 
-  /** Create a new {@link UnknownFieldSet.Builder}. */
+  /** Create a new {@link Builder}. */
   public static Builder newBuilder() {
-    return new Builder();
+    return Builder.create();
   }
 
   /**
-   * Create a new {@link UnknownFieldSet.Builder} and initialize it to be a copy
+   * Create a new {@link Builder} and initialize it to be a copy
    * of {@code copyFrom}.
    */
-  public static Builder newBuilder(UnknownFieldSet copyFrom) {
-    return new Builder().mergeFrom(copyFrom);
+  public static Builder newBuilder(final UnknownFieldSet copyFrom) {
+    return newBuilder().mergeFrom(copyFrom);
   }
 
   /** Get an empty {@code UnknownFieldSet}. */
   public static UnknownFieldSet getDefaultInstance() {
     return defaultInstance;
   }
-  private static UnknownFieldSet defaultInstance =
+  public UnknownFieldSet getDefaultInstanceForType() {
+    return defaultInstance;
+  }
+  private static final UnknownFieldSet defaultInstance =
     new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
 
   /**
    * Construct an {@code UnknownFieldSet} around the given map.  The map is
    * expected to be immutable.
    */
-  private UnknownFieldSet(Map<Integer, Field> fields) {
+  private UnknownFieldSet(final Map<Integer, Field> fields) {
     this.fields = fields;
   }
   private Map<Integer, Field> fields;
 
   @Override
-  public boolean equals(Object other) {
+  public boolean equals(final Object other) {
     if (this == other) {
       return true;
     }
     return (other instanceof UnknownFieldSet) &&
-        this.fields.equals(((UnknownFieldSet) other).fields);
+           fields.equals(((UnknownFieldSet) other).fields);
   }
 
   @Override
   public int hashCode() {
-    return this.fields.hashCode();
+    return fields.hashCode();
   }
 
   /** Get a map of fields in the set by number. */
@@ -106,7 +111,7 @@
   }
 
   /** Check if the given field number is present in the set. */
-  public boolean hasField(int number) {
+  public boolean hasField(final int number) {
     return fields.containsKey(number);
   }
 
@@ -114,14 +119,14 @@
    * Get a field by number.  Returns an empty field if not present.  Never
    * returns {@code null}.
    */
-  public Field getField(int number) {
-    Field result = fields.get(number);
+  public Field getField(final int number) {
+    final Field result = fields.get(number);
     return (result == null) ? Field.getDefaultInstance() : result;
   }
 
   /** Serializes the set and writes it to {@code output}. */
-  public void writeTo(CodedOutputStream output) throws IOException {
-    for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       entry.getValue().writeTo(entry.getKey(), output);
     }
   }
@@ -131,7 +136,8 @@
    * just a trivial wrapper around
    * {@link TextFormat#printToString(UnknownFieldSet)}.
    */
-  public final String toString() {
+  @Override
+  public String toString() {
     return TextFormat.printToString(this);
   }
 
@@ -139,13 +145,13 @@
    * Serializes the message to a {@code ByteString} and returns it. This is
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
-  public final ByteString toByteString() {
+  public ByteString toByteString() {
     try {
-      ByteString.CodedBuilder out =
+      final ByteString.CodedBuilder out =
         ByteString.newCodedBuilder(getSerializedSize());
       writeTo(out.getCodedOutput());
       return out.build();
-    } catch (IOException e) {
+    } catch (final IOException e) {
       throw new RuntimeException(
         "Serializing to a ByteString threw an IOException (should " +
         "never happen).", e);
@@ -156,14 +162,14 @@
    * Serializes the message to a {@code byte} array and returns it.  This is
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
-  public final byte[] toByteArray() {
+  public byte[] toByteArray() {
     try {
-      byte[] result = new byte[getSerializedSize()];
-      CodedOutputStream output = CodedOutputStream.newInstance(result);
+      final byte[] result = new byte[getSerializedSize()];
+      final CodedOutputStream output = CodedOutputStream.newInstance(result);
       writeTo(output);
       output.checkNoSpaceLeft();
       return result;
-    } catch (IOException e) {
+    } catch (final IOException e) {
       throw new RuntimeException(
         "Serializing to a byte array threw an IOException " +
         "(should never happen).", e);
@@ -174,8 +180,15 @@
    * Serializes the message and writes it to {@code output}.  This is just a
    * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
-  public final void writeTo(OutputStream output) throws IOException {
-    CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+  public void writeTo(final OutputStream output) throws IOException {
+    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  public void writeDelimitedTo(OutputStream output) throws IOException {
+    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+    codedOutput.writeRawVarint32(getSerializedSize());
     writeTo(codedOutput);
     codedOutput.flush();
   }
@@ -183,7 +196,7 @@
   /** Get the number of bytes required to encode this set. */
   public int getSerializedSize() {
     int result = 0;
-    for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       result += entry.getValue().getSerializedSize(entry.getKey());
     }
     return result;
@@ -193,9 +206,9 @@
    * Serializes the set and writes it to {@code output} using
    * {@code MessageSet} wire format.
    */
-  public void writeAsMessageSetTo(CodedOutputStream output)
+  public void writeAsMessageSetTo(final CodedOutputStream output)
       throws IOException {
-    for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       entry.getValue().writeAsMessageSetExtensionTo(
         entry.getKey(), output);
     }
@@ -207,37 +220,51 @@
    */
   public int getSerializedSizeAsMessageSet() {
     int result = 0;
-    for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       result += entry.getValue().getSerializedSizeAsMessageSetExtension(
         entry.getKey());
     }
     return result;
   }
 
+  public boolean isInitialized() {
+    // UnknownFieldSets do not have required fields, so they are always
+    // initialized.
+    return true;
+  }
+
   /** Parse an {@code UnknownFieldSet} from the given input stream. */
-  static public UnknownFieldSet parseFrom(CodedInputStream input)
+  public static UnknownFieldSet parseFrom(final CodedInputStream input)
                                           throws IOException {
     return newBuilder().mergeFrom(input).build();
   }
 
   /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
-  public static UnknownFieldSet parseFrom(ByteString data)
+  public static UnknownFieldSet parseFrom(final ByteString data)
       throws InvalidProtocolBufferException {
     return newBuilder().mergeFrom(data).build();
   }
 
   /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
-  public static UnknownFieldSet parseFrom(byte[] data)
+  public static UnknownFieldSet parseFrom(final byte[] data)
       throws InvalidProtocolBufferException {
     return newBuilder().mergeFrom(data).build();
   }
 
   /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
-  public static UnknownFieldSet parseFrom(InputStream input)
+  public static UnknownFieldSet parseFrom(final InputStream input)
                                           throws IOException {
     return newBuilder().mergeFrom(input).build();
   }
 
+  public Builder newBuilderForType() {
+    return newBuilder();
+  }
+
+  public Builder toBuilder() {
+    return newBuilder().mergeFrom(this);
+  }
+
   /**
    * Builder for {@link UnknownFieldSet}s.
    *
@@ -250,21 +277,35 @@
    *
    * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
    */
-  public static final class Builder {
+  public static final class Builder implements MessageLite.Builder {
+    private static ThreadLocalQuickQueue<Builder> builders =
+      new ThreadLocalQuickQueue<Builder>();
+
+    // This constructor should never be called directly (except from 'create').
     private Builder() {}
-    private Map<Integer, Field> fields = new TreeMap<Integer, Field>();
+
+    private Map<Integer, Field> fields;
 
     // Optimization:  We keep around a builder for the last field that was
     //   modified so that we can efficiently add to it multiple times in a
     //   row (important when parsing an unknown repeated field).
-    int lastFieldNumber = 0;
-    Field.Builder lastField = null;
+    private int lastFieldNumber;
+    private Field.Builder lastField;
+
+    private static Builder create() {
+      Builder builder = builders.get().poll();
+      if (builder == null) {
+        builder = new Builder();
+      }
+      builder.reinitialize();
+      return builder;
+    }
 
     /**
      * Get a field builder for the given field number which includes any
      * values that already exist.
      */
-    private Field.Builder getFieldBuilder(int number) {
+    private Field.Builder getFieldBuilder(final int number) {
       if (lastField != null) {
         if (number == lastFieldNumber) {
           return lastField;
@@ -275,7 +316,7 @@
       if (number == 0) {
         return null;
       } else {
-        Field existing = fields.get(number);
+        final Field existing = fields.get(number);
         lastFieldNumber = number;
         lastField = Field.newBuilder();
         if (existing != null) {
@@ -289,26 +330,48 @@
      * Build the {@link UnknownFieldSet} and return it.
      *
      * <p>Once {@code build()} has been called, the {@code Builder} will no
-     * longer be usable.  Calling any method after {@code build()} will throw
-     * {@code NullPointerException}.
+     * longer be usable.  Calling any method after {@code build()} will result
+     * in undefined behavior and can cause a {@code NullPointerException} to be
+     * thrown.
      */
     public UnknownFieldSet build() {
       getFieldBuilder(0);  // Force lastField to be built.
-      UnknownFieldSet result;
+      final UnknownFieldSet result;
       if (fields.isEmpty()) {
         result = getDefaultInstance();
       } else {
         result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
       }
       fields = null;
+      builders.get().offer(this);
       return result;
     }
 
+    public UnknownFieldSet buildPartial() {
+      // No required fields, so this is the same as build().
+      return build();
+    }
+
+    @Override
+    public Builder clone() {
+      getFieldBuilder(0);  // Force lastField to be built.
+      return UnknownFieldSet.newBuilder().mergeFrom(
+          new UnknownFieldSet(fields));
+    }
+
+    public UnknownFieldSet getDefaultInstanceForType() {
+      return UnknownFieldSet.getDefaultInstance();
+    }
+
+    private void reinitialize() {
+      fields = Collections.emptyMap();
+      lastFieldNumber = 0;
+      lastField = null;
+    }
+
     /** Reset the builder to an empty set. */
     public Builder clear() {
-      fields = new TreeMap<Integer, Field>();
-      lastFieldNumber = 0;
-      lastField = null;
+      reinitialize();
       return this;
     }
 
@@ -317,9 +380,9 @@
      * exists in both sets, {@code other}'s values for that field will be
      * appended to the values in this set.
      */
-    public Builder mergeFrom(UnknownFieldSet other) {
+    public Builder mergeFrom(final UnknownFieldSet other) {
       if (other != getDefaultInstance()) {
-        for (Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
+        for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
           mergeField(entry.getKey(), entry.getValue());
         }
       }
@@ -330,7 +393,7 @@
      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
      * number already exists, the two are merged.
      */
-    public Builder mergeField(int number, Field field) {
+    public Builder mergeField(final int number, final Field field) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
@@ -350,7 +413,7 @@
      * value.  This is used in particular when an unknown enum value is
      * encountered.
      */
-    public Builder mergeVarintField(int number, int value) {
+    public Builder mergeVarintField(final int number, final int value) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
@@ -359,7 +422,7 @@
     }
 
     /** Check if the given field number is present in the set. */
-    public boolean hasField(int number) {
+    public boolean hasField(final int number) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
@@ -370,7 +433,7 @@
      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
      * number already exists, it is removed.
      */
-    public Builder addField(int number, Field field) {
+    public Builder addField(final int number, final Field field) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
@@ -379,6 +442,9 @@
         lastField = null;
         lastFieldNumber = 0;
       }
+      if (fields.isEmpty()) {
+        fields = new TreeMap<Integer,Field>();
+      }
       fields.put(number, field);
       return this;
     }
@@ -396,9 +462,9 @@
      * Parse an entire message from {@code input} and merge its fields into
      * this set.
      */
-    public Builder mergeFrom(CodedInputStream input) throws IOException {
+    public Builder mergeFrom(final CodedInputStream input) throws IOException {
       while (true) {
-        int tag = input.readTag();
+        final int tag = input.readTag();
         if (tag == 0 || !mergeFieldFrom(tag, input)) {
           break;
         }
@@ -411,9 +477,9 @@
      * @param tag The field's tag number, which was already parsed.
      * @return {@code false} if the tag is an engroup tag.
      */
-    public boolean mergeFieldFrom(int tag, CodedInputStream input)
+    public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
                                   throws IOException {
-      int number = WireFormat.getTagFieldNumber(tag);
+      final int number = WireFormat.getTagFieldNumber(tag);
       switch (WireFormat.getTagWireType(tag)) {
         case WireFormat.WIRETYPE_VARINT:
           getFieldBuilder(number).addVarint(input.readInt64());
@@ -424,12 +490,12 @@
         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
           getFieldBuilder(number).addLengthDelimited(input.readBytes());
           return true;
-        case WireFormat.WIRETYPE_START_GROUP: {
-          UnknownFieldSet.Builder subBuilder = UnknownFieldSet.newBuilder();
-          input.readUnknownGroup(number, subBuilder);
+        case WireFormat.WIRETYPE_START_GROUP:
+          final Builder subBuilder = newBuilder();
+          input.readGroup(number, subBuilder,
+                          ExtensionRegistry.getEmptyRegistry());
           getFieldBuilder(number).addGroup(subBuilder.build());
           return true;
-        }
         case WireFormat.WIRETYPE_END_GROUP:
           return false;
         case WireFormat.WIRETYPE_FIXED32:
@@ -445,16 +511,16 @@
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      */
-    public Builder mergeFrom(ByteString data)
+    public Builder mergeFrom(final ByteString data)
         throws InvalidProtocolBufferException {
       try {
-        CodedInputStream input = data.newCodedInput();
+        final CodedInputStream input = data.newCodedInput();
         mergeFrom(input);
         input.checkLastTagWas(0);
         return this;
-      } catch (InvalidProtocolBufferException e) {
+      } catch (final InvalidProtocolBufferException e) {
         throw e;
-      } catch (IOException e) {
+      } catch (final IOException e) {
         throw new RuntimeException(
           "Reading from a ByteString threw an IOException (should " +
           "never happen).", e);
@@ -466,10 +532,69 @@
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      */
-    public Builder mergeFrom(byte[] data)
+    public Builder mergeFrom(final byte[] data)
         throws InvalidProtocolBufferException {
       try {
-        CodedInputStream input = CodedInputStream.newInstance(data);
+        final CodedInputStream input = CodedInputStream.newInstance(data);
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return this;
+      } catch (final InvalidProtocolBufferException e) {
+        throw e;
+      } catch (final IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    /**
+     * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
+     * set being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    public Builder mergeFrom(final InputStream input) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput);
+      codedInput.checkLastTagWas(0);
+      return this;
+    }
+
+    public Builder mergeDelimitedFrom(InputStream input)
+        throws IOException {
+      final int size = CodedInputStream.readRawVarint32(input);
+      final InputStream limitedInput =
+        new AbstractMessage.Builder.LimitedInputStream(input, size);
+      return mergeFrom(limitedInput, null);
+    }
+
+    public Builder mergeDelimitedFrom(
+        InputStream input,
+        ExtensionRegistryLite extensionRegistry) throws IOException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(input);
+    }
+
+    public Builder mergeFrom(
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry) throws IOException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(input);
+    }
+
+    public Builder mergeFrom(
+        ByteString data,
+        ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(data);
+    }
+
+    public Builder mergeFrom(byte[] data, int off, int len)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
         mergeFrom(input);
         input.checkLastTagWas(0);
         return this;
@@ -482,16 +607,33 @@
       }
     }
 
-    /**
-     * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
-     * set being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream)}.
-     */
-    public Builder mergeFrom(InputStream input) throws IOException {
-      CodedInputStream codedInput = CodedInputStream.newInstance(input);
-      mergeFrom(codedInput);
-      codedInput.checkLastTagWas(0);
-      return this;
+    public Builder mergeFrom(
+        byte[] data,
+        ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(data);
+    }
+
+    public Builder mergeFrom(
+        byte[] data, int off, int len,
+        ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(data, off, len);
+    }
+
+    public Builder mergeFrom(
+        InputStream input,
+        ExtensionRegistryLite extensionRegistry) throws IOException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(input);
+    }
+
+    public boolean isInitialized() {
+      // UnknownFieldSets do not have required fields, so they are always
+      // initialized.
+      return true;
     }
   }
 
@@ -510,7 +652,7 @@
    * wire types.
    *
    * <p>{@code Field} is an immutable class.  To construct one, you must use a
-   * {@link Field.Builder}.
+   * {@link Builder}.
    *
    * @see UnknownFieldSet
    */
@@ -519,22 +661,22 @@
 
     /** Construct a new {@link Builder}. */
     public static Builder newBuilder() {
-      return new Builder();
+      return Builder.create();
     }
 
     /**
      * Construct a new {@link Builder} and initialize it to a copy of
      * {@code copyFrom}.
      */
-    public static Builder newBuilder(Field copyFrom) {
-      return new Builder().mergeFrom(copyFrom);
+    public static Builder newBuilder(final Field copyFrom) {
+      return newBuilder().mergeFrom(copyFrom);
     }
 
     /** Get an empty {@code Field}. */
     public static Field getDefaultInstance() {
-      return defaultInstance;
+      return fieldDefaultInstance;
     }
-    private static Field defaultInstance = newBuilder().build();
+    private static final Field fieldDefaultInstance = newBuilder().build();
 
     /** Get the list of varint values for this field. */
     public List<Long> getVarintList()               { return varint;          }
@@ -556,14 +698,14 @@
     public List<UnknownFieldSet> getGroupList()      { return group;           }
 
     @Override
-    public boolean equals(Object other) {
+    public boolean equals(final Object other) {
       if (this == other) {
         return true;
       }
       if (!(other instanceof Field)) {
         return false;
       }
-      return Arrays.equals(this.getIdentityArray(),
+      return Arrays.equals(getIdentityArray(),
           ((Field) other).getIdentityArray());
     }
 
@@ -574,37 +716,37 @@
 
     /**
      * Returns the array of objects to be used to uniquely identify this
-     * {@link UnknownFieldSet.Field} instance.
+     * {@link Field} instance.
      */
     private Object[] getIdentityArray() {
       return new Object[] {
-          this.varint,
-          this.fixed32,
-          this.fixed64,
-          this.lengthDelimited,
-          this.group};
+          varint,
+          fixed32,
+          fixed64,
+          lengthDelimited,
+          group};
     }
 
     /**
      * Serializes the field, including field number, and writes it to
      * {@code output}.
      */
-    public void writeTo(int fieldNumber, CodedOutputStream output)
+    public void writeTo(final int fieldNumber, final CodedOutputStream output)
                         throws IOException {
-      for (long value : varint) {
+      for (final long value : varint) {
         output.writeUInt64(fieldNumber, value);
       }
-      for (int value : fixed32) {
+      for (final int value : fixed32) {
         output.writeFixed32(fieldNumber, value);
       }
-      for (long value : fixed64) {
+      for (final long value : fixed64) {
         output.writeFixed64(fieldNumber, value);
       }
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         output.writeBytes(fieldNumber, value);
       }
-      for (UnknownFieldSet value : group) {
-        output.writeUnknownGroup(fieldNumber, value);
+      for (final UnknownFieldSet value : group) {
+        output.writeGroup(fieldNumber, value);
       }
     }
 
@@ -612,22 +754,22 @@
      * Get the number of bytes required to encode this field, including field
      * number.
      */
-    public int getSerializedSize(int fieldNumber) {
+    public int getSerializedSize(final int fieldNumber) {
       int result = 0;
-      for (long value : varint) {
+      for (final long value : varint) {
         result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
       }
-      for (int value : fixed32) {
+      for (final int value : fixed32) {
         result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
       }
-      for (long value : fixed64) {
+      for (final long value : fixed64) {
         result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
       }
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         result += CodedOutputStream.computeBytesSize(fieldNumber, value);
       }
-      for (UnknownFieldSet value : group) {
-        result += CodedOutputStream.computeUnknownGroupSize(fieldNumber, value);
+      for (final UnknownFieldSet value : group) {
+        result += CodedOutputStream.computeGroupSize(fieldNumber, value);
       }
       return result;
     }
@@ -637,10 +779,10 @@
      * {@code output}, using {@code MessageSet} wire format.
      */
     public void writeAsMessageSetExtensionTo(
-        int fieldNumber,
-        CodedOutputStream output)
+        final int fieldNumber,
+        final CodedOutputStream output)
         throws IOException {
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         output.writeRawMessageSetExtension(fieldNumber, value);
       }
     }
@@ -649,9 +791,9 @@
      * Get the number of bytes required to encode this field, including field
      * number, using {@code MessageSet} wire format.
      */
-    public int getSerializedSizeAsMessageSetExtension(int fieldNumber) {
+    public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
       int result = 0;
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         result += CodedOutputStream.computeRawMessageSetExtensionSize(
           fieldNumber, value);
       }
@@ -670,13 +812,29 @@
      * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
      */
     public static final class Builder {
+      private static ThreadLocalQuickQueue<Builder> builders =
+        new ThreadLocalQuickQueue<Builder>();
+
+      // This constructor should never be called directly (except from 'create').
       private Builder() {}
-      private Field result = new Field();
+
+      private static Builder create() {
+        Builder builder = builders.get().poll();
+        if (builder == null) {
+          builder = new Builder();
+        }
+
+        builder.result = new Field();
+        return builder;
+      }
+
+      private Field result;
 
       /**
        * Build the field.  After {@code build()} has been called, the
        * {@code Builder} is no longer usable.  Calling any other method will
-       * throw a {@code NullPointerException}.
+       * result in undefined behavior and can cause a
+       * {@code NullPointerException} to be thrown.
        */
       public Field build() {
         if (result.varint == null) {
@@ -706,8 +864,9 @@
           result.group = Collections.unmodifiableList(result.group);
         }
 
-        Field returnMe = result;
+        final Field returnMe = result;
         result = null;
+        builders.get().offer(this);
         return returnMe;
       }
 
@@ -722,7 +881,7 @@
        * of values, {@code other}'s values are append to the ones in this
        * field.
        */
-      public Builder mergeFrom(Field other) {
+      public Builder mergeFrom(final Field other) {
         if (!other.varint.isEmpty()) {
           if (result.varint == null) {
             result.varint = new ArrayList<Long>();
@@ -757,7 +916,7 @@
       }
 
       /** Add a varint value. */
-      public Builder addVarint(long value) {
+      public Builder addVarint(final long value) {
         if (result.varint == null) {
           result.varint = new ArrayList<Long>();
         }
@@ -766,7 +925,7 @@
       }
 
       /** Add a fixed32 value. */
-      public Builder addFixed32(int value) {
+      public Builder addFixed32(final int value) {
         if (result.fixed32 == null) {
           result.fixed32 = new ArrayList<Integer>();
         }
@@ -775,7 +934,7 @@
       }
 
       /** Add a fixed64 value. */
-      public Builder addFixed64(long value) {
+      public Builder addFixed64(final long value) {
         if (result.fixed64 == null) {
           result.fixed64 = new ArrayList<Long>();
         }
@@ -784,7 +943,7 @@
       }
 
       /** Add a length-delimited value. */
-      public Builder addLengthDelimited(ByteString value) {
+      public Builder addLengthDelimited(final ByteString value) {
         if (result.lengthDelimited == null) {
           result.lengthDelimited = new ArrayList<ByteString>();
         }
@@ -793,7 +952,7 @@
       }
 
       /** Add an embedded group. */
-      public Builder addGroup(UnknownFieldSet value) {
+      public Builder addGroup(final UnknownFieldSet value) {
         if (result.group == null) {
           result.group = new ArrayList<UnknownFieldSet>();
         }
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index 2faf244..3b0bdcd 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -56,54 +56,84 @@
   static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
 
   /** Given a tag value, determines the wire type (the lower 3 bits). */
-  static int getTagWireType(int tag) {
+  static int getTagWireType(final int tag) {
     return tag & TAG_TYPE_MASK;
   }
 
   /** Given a tag value, determines the field number (the upper 29 bits). */
-  public static int getTagFieldNumber(int tag) {
+  public static int getTagFieldNumber(final int tag) {
     return tag >>> TAG_TYPE_BITS;
   }
 
   /** Makes a tag value given a field number and wire type. */
-  static int makeTag(int fieldNumber, int wireType) {
+  static int makeTag(final int fieldNumber, final int wireType) {
     return (fieldNumber << TAG_TYPE_BITS) | wireType;
   }
 
-  static int getWireFormatForFieldType(Descriptors.FieldDescriptor.Type type) {
-    switch (type) {
-      case DOUBLE  : return WIRETYPE_FIXED64;
-      case FLOAT   : return WIRETYPE_FIXED32;
-      case INT64   : return WIRETYPE_VARINT;
-      case UINT64  : return WIRETYPE_VARINT;
-      case INT32   : return WIRETYPE_VARINT;
-      case FIXED64 : return WIRETYPE_FIXED64;
-      case FIXED32 : return WIRETYPE_FIXED32;
-      case BOOL    : return WIRETYPE_VARINT;
-      case STRING  : return WIRETYPE_LENGTH_DELIMITED;
-      case GROUP   : return WIRETYPE_START_GROUP;
-      case MESSAGE : return WIRETYPE_LENGTH_DELIMITED;
-      case BYTES   : return WIRETYPE_LENGTH_DELIMITED;
-      case UINT32  : return WIRETYPE_VARINT;
-      case ENUM    : return WIRETYPE_VARINT;
-      case SFIXED32: return WIRETYPE_FIXED32;
-      case SFIXED64: return WIRETYPE_FIXED64;
-      case SINT32  : return WIRETYPE_VARINT;
-      case SINT64  : return WIRETYPE_VARINT;
+  /**
+   * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}.  This is
+   * only here to support the lite runtime and should not be used by users.
+   */
+  public enum JavaType {
+    INT(0),
+    LONG(0L),
+    FLOAT(0F),
+    DOUBLE(0D),
+    BOOLEAN(false),
+    STRING(""),
+    BYTE_STRING(ByteString.EMPTY),
+    ENUM(null),
+    MESSAGE(null);
+
+    JavaType(final Object defaultDefault) {
+      this.defaultDefault = defaultDefault;
     }
 
-    throw new RuntimeException(
-      "There is no way to get here, but the compiler thinks otherwise.");
+    /**
+     * The default default value for fields of this type, if it's a primitive
+     * type.
+     */
+    Object getDefaultDefault() {
+      return defaultDefault;
+    }
+
+    private final Object defaultDefault;
   }
 
-  /** Given a field descriptor, returns the wire type. This differs from
-   * getWireFormatForFieldType for packed repeated fields. */
-  static int getWireFormatForField(Descriptors.FieldDescriptor descriptor) {
-    if (descriptor.getOptions().getPacked()) {
-      return WIRETYPE_LENGTH_DELIMITED;
-    } else {
-      return getWireFormatForFieldType(descriptor.getType());
+  /**
+   * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}.  This is
+   * only here to support the lite runtime and should not be used by users.
+   */
+  public enum FieldType {
+    DOUBLE  (JavaType.DOUBLE     , WIRETYPE_FIXED64         ),
+    FLOAT   (JavaType.FLOAT      , WIRETYPE_FIXED32         ),
+    INT64   (JavaType.LONG       , WIRETYPE_VARINT          ),
+    UINT64  (JavaType.LONG       , WIRETYPE_VARINT          ),
+    INT32   (JavaType.INT        , WIRETYPE_VARINT          ),
+    FIXED64 (JavaType.LONG       , WIRETYPE_FIXED64         ),
+    FIXED32 (JavaType.INT        , WIRETYPE_FIXED32         ),
+    BOOL    (JavaType.BOOLEAN    , WIRETYPE_VARINT          ),
+    STRING  (JavaType.STRING     , WIRETYPE_LENGTH_DELIMITED),
+    GROUP   (JavaType.MESSAGE    , WIRETYPE_START_GROUP     ),
+    MESSAGE (JavaType.MESSAGE    , WIRETYPE_LENGTH_DELIMITED),
+    BYTES   (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED),
+    UINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
+    ENUM    (JavaType.ENUM       , WIRETYPE_VARINT          ),
+    SFIXED32(JavaType.INT        , WIRETYPE_FIXED32         ),
+    SFIXED64(JavaType.LONG       , WIRETYPE_FIXED64         ),
+    SINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
+    SINT64  (JavaType.LONG       , WIRETYPE_VARINT          );
+
+    FieldType(final JavaType javaType, final int wireType) {
+      this.javaType = javaType;
+      this.wireType = wireType;
     }
+
+    private final JavaType javaType;
+    private final int wireType;
+
+    public JavaType getJavaType() { return javaType; }
+    public int getWireType() { return wireType; }
   }
 
   // Field numbers for feilds in MessageSet wire format.
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 84a7597..6fa5626 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -367,4 +367,34 @@
     assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
       method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
   }
+
+  /**
+   * Test that the FieldDescriptor.Type enum is the same as the
+   * WireFormat.FieldType enum.
+   */
+  public void testFieldTypeTablesMatch() throws Exception {
+    FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
+    WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
+
+    assertEquals(values1.length, values2.length);
+
+    for (int i = 0; i < values1.length; i++) {
+      assertEquals(values1[i].toString(), values2[i].toString());
+    }
+  }
+
+  /**
+   * Test that the FieldDescriptor.JavaType enum is the same as the
+   * WireFormat.JavaType enum.
+   */
+  public void testJavaTypeTablesMatch() throws Exception {
+    FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
+    WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
+
+    assertEquals(values1.length, values2.length);
+
+    for (int i = 0; i < values1.length; i++) {
+      assertEquals(values1[i].toString(), values2[i].toString());
+    }
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
index 120b0f1..aabccda 100644
--- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -73,6 +73,18 @@
     }
   }
 
+  public void testClearAfterBuildError() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    builder.build();
+    try {
+      builder.clear();
+      fail("Should have thrown exception.");
+    } catch (IllegalStateException e) {
+      // Success.
+    }
+  }
+
   public void testDynamicMessageSettersRejectNull() throws Exception {
     Message.Builder builder =
       DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 58d8219..cdf60c5 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -43,6 +43,8 @@
 import protobuf_unittest.MessageWithNoOuter;
 import protobuf_unittest.EnumWithNoOuter;
 import protobuf_unittest.ServiceWithNoOuter;
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 
 import junit.framework.TestCase;
 import java.util.Arrays;
@@ -82,6 +84,17 @@
     }
   }
 
+  public void testClearAfterBuildError() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.build();
+    try {
+      builder.clear();
+      fail("Should have thrown exception.");
+    } catch (IllegalStateException e) {
+      // Success.
+    }
+  }
+
   public void testSettersRejectNull() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     try {
@@ -338,6 +351,16 @@
         instanceof ProtocolMessageEnum);
   }
 
+  public void testEnumMap() throws Exception {
+    Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
+
+    for (ForeignEnum value : ForeignEnum.values()) {
+      assertEquals(value, map.findValueByNumber(value.getNumber()));
+    }
+
+    assertTrue(map.findValueByNumber(12345) == null);
+  }
+
   // =================================================================
   // Extensions.
 
@@ -420,6 +443,12 @@
         .getExtensionCount(UnittestProto.repeatedInt32Extension));
   }
 
+  public void testExtensionCopy() throws Exception {
+    TestAllExtensions original = TestUtil.getAllExtensionsSet();
+    TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
+    TestUtil.assertAllExtensionsSet(copy);
+  }
+
   public void testExtensionMergeFrom() throws Exception {
     TestAllExtensions original =
       TestAllExtensions.newBuilder()
@@ -432,6 +461,66 @@
   }
 
   // =================================================================
+  // Lite Extensions.
+
+  // We test lite extensions directly because they have a separate
+  // implementation from full extensions.  In contrast, we do not test
+  // lite fields directly since they are implemented exactly the same as
+  // regular fields.
+
+  public void testLiteExtensionAccessors() throws Exception {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    TestUtil.setAllExtensions(builder);
+    TestAllExtensionsLite message = builder.build();
+    TestUtil.assertAllExtensionsSet(message);
+  }
+
+  public void testLiteExtensionRepeatedSetters() throws Exception {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    TestUtil.setAllExtensions(builder);
+    TestUtil.modifyRepeatedExtensions(builder);
+    TestAllExtensionsLite message = builder.build();
+    TestUtil.assertRepeatedExtensionsModified(message);
+  }
+
+  public void testLiteExtensionDefaults() throws Exception {
+    TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance());
+    TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build());
+  }
+
+  public void testClearLiteExtension() throws Exception {
+    // clearExtension() is not actually used in TestUtil, so try it manually.
+    assertFalse(
+      TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 1)
+        .clearExtension(UnittestLite.optionalInt32ExtensionLite)
+        .hasExtension(UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(0,
+      TestAllExtensionsLite.newBuilder()
+        .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1)
+        .clearExtension(UnittestLite.repeatedInt32ExtensionLite)
+        .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite));
+  }
+
+  public void testLiteExtensionCopy() throws Exception {
+    TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet();
+    TestAllExtensionsLite copy =
+        TestAllExtensionsLite.newBuilder(original).build();
+    TestUtil.assertAllExtensionsSet(copy);
+  }
+
+  public void testLiteExtensionMergeFrom() throws Exception {
+    TestAllExtensionsLite original =
+      TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build();
+    TestAllExtensionsLite merged =
+        TestAllExtensionsLite.newBuilder().mergeFrom(original).build();
+    assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(
+        1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite));
+  }
+
+  // =================================================================
   // multiple_files_test
 
   public void testMultipleFilesOption() throws Exception {
diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java
new file mode 100644
index 0000000..9dd730c
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/LiteTest.java
@@ -0,0 +1,114 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+
+import junit.framework.TestCase;
+
+/**
+ * Test lite runtime.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class LiteTest extends TestCase {
+  public void setUp() throws Exception {
+    // Test that nested extensions are initialized correctly even if the outer
+    // class has not been accessed directly.  This was once a bug with lite
+    // messages.
+    //
+    // We put this in setUp() rather than in its own test method because we
+    // need to make sure it runs before any actual tests.
+    assertTrue(TestNestedExtensionLite.nestedExtension != null);
+  }
+
+  public void testLite() throws Exception {
+    // Since lite messages are a subset of regular messages, we can mostly
+    // assume that the functionality of lite messages is already thoroughly
+    // tested by the regular tests.  All this test really verifies is that
+    // a proto with optimize_for = LITE_RUNTIME compiles correctly when
+    // linked only against the lite library.  That is all tested at compile
+    // time, leaving not much to do in this method.  Let's just do some random
+    // stuff to make sure the lite message is actually here and usable.
+
+    TestAllTypesLite message =
+      TestAllTypesLite.newBuilder()
+                      .setOptionalInt32(123)
+                      .addRepeatedString("hello")
+                      .setOptionalNestedMessage(
+                          TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+                      .build();
+
+    ByteString data = message.toByteString();
+
+    TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data);
+
+    assertEquals(123, message2.getOptionalInt32());
+    assertEquals(1, message2.getRepeatedStringCount());
+    assertEquals("hello", message2.getRepeatedString(0));
+    assertEquals(7, message2.getOptionalNestedMessage().getBb());
+  }
+
+  public void testLiteExtensions() throws Exception {
+    // TODO(kenton):  Unlike other features of the lite library, extensions are
+    //   implemented completely differently from the regular library.  We
+    //   need to test them more thoroughly, once they are fully-implemented.
+
+    TestAllExtensionsLite message =
+      TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+        .addExtension(UnittestLite.repeatedStringExtensionLite, "hello")
+        .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+            TestAllTypesLite.NestedEnum.BAZ)
+        .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+        .build();
+
+    // Test copying a message, since coping extensions actually does use a
+    // different code path between lite and regular libraries, and as of this
+    // writing, parsing hasn't been implemented yet.
+    TestAllExtensionsLite message2 = message.toBuilder().build();
+
+    assertEquals(123, (int) message2.getExtension(
+        UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(1, message2.getExtensionCount(
+        UnittestLite.repeatedStringExtensionLite));
+    assertEquals("hello", message2.getExtension(
+        UnittestLite.repeatedStringExtensionLite, 0));
+    assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension(
+        UnittestLite.optionalNestedEnumExtensionLite));
+    assertEquals(7, message2.getExtension(
+        UnittestLite.optionalNestedMessageExtensionLite).getBb());
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 2f47b71..805c42a 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -31,6 +31,7 @@
 package com.google.protobuf;
 
 import protobuf_unittest.UnittestProto;
+import com.google.protobuf.UnittestLite;
 
 // The static imports are to avoid 100+ char lines.  The following is roughly equivalent to
 // import static protobuf_unittest.UnittestProto.*;
@@ -123,6 +124,95 @@
 import static protobuf_unittest.UnittestProto.packedBoolExtension;
 import static protobuf_unittest.UnittestProto.packedEnumExtension;
 
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
+
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestPackedExtensions;
@@ -132,6 +222,14 @@
 import com.google.protobuf.test.UnittestImport.ImportMessage;
 import com.google.protobuf.test.UnittestImport.ImportEnum;
 
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+
 import junit.framework.Assert;
 
 import java.io.File;
@@ -179,6 +277,12 @@
     return builder.build();
   }
 
+  public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    setAllExtensions(builder);
+    return builder.build();
+  }
+
   public static TestPackedTypes getPackedSet() {
     TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
     setPackedFields(builder);
@@ -191,6 +295,13 @@
     return builder.build();
   }
 
+  public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
+    TestPackedExtensionsLite.Builder builder =
+        TestPackedExtensionsLite.newBuilder();
+    setPackedExtensions(builder);
+    return builder.build();
+  }
+
   /**
    * Set every field of {@code message} to the values expected by
    * {@code assertAllFieldsSet()}.
@@ -809,6 +920,90 @@
     Assert.assertEquals("525", message.getRepeatedCord(1));
   }
 
+  /**
+   * Set every field of {@code message} to a unique value.
+   */
+  public static void setPackedFields(TestPackedTypes.Builder message) {
+    message.addPackedInt32   (601);
+    message.addPackedInt64   (602);
+    message.addPackedUint32  (603);
+    message.addPackedUint64  (604);
+    message.addPackedSint32  (605);
+    message.addPackedSint64  (606);
+    message.addPackedFixed32 (607);
+    message.addPackedFixed64 (608);
+    message.addPackedSfixed32(609);
+    message.addPackedSfixed64(610);
+    message.addPackedFloat   (611);
+    message.addPackedDouble  (612);
+    message.addPackedBool    (true);
+    message.addPackedEnum    (ForeignEnum.FOREIGN_BAR);
+    // Add a second one of each field.
+    message.addPackedInt32   (701);
+    message.addPackedInt64   (702);
+    message.addPackedUint32  (703);
+    message.addPackedUint64  (704);
+    message.addPackedSint32  (705);
+    message.addPackedSint64  (706);
+    message.addPackedFixed32 (707);
+    message.addPackedFixed64 (708);
+    message.addPackedSfixed32(709);
+    message.addPackedSfixed64(710);
+    message.addPackedFloat   (711);
+    message.addPackedDouble  (712);
+    message.addPackedBool    (false);
+    message.addPackedEnum    (ForeignEnum.FOREIGN_BAZ);
+  }
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all fields of
+   * {@code message} are set to the values assigned by {@code setPackedFields}.
+   */
+  public static void assertPackedFieldsSet(TestPackedTypes message) {
+    Assert.assertEquals(2, message.getPackedInt32Count   ());
+    Assert.assertEquals(2, message.getPackedInt64Count   ());
+    Assert.assertEquals(2, message.getPackedUint32Count  ());
+    Assert.assertEquals(2, message.getPackedUint64Count  ());
+    Assert.assertEquals(2, message.getPackedSint32Count  ());
+    Assert.assertEquals(2, message.getPackedSint64Count  ());
+    Assert.assertEquals(2, message.getPackedFixed32Count ());
+    Assert.assertEquals(2, message.getPackedFixed64Count ());
+    Assert.assertEquals(2, message.getPackedSfixed32Count());
+    Assert.assertEquals(2, message.getPackedSfixed64Count());
+    Assert.assertEquals(2, message.getPackedFloatCount   ());
+    Assert.assertEquals(2, message.getPackedDoubleCount  ());
+    Assert.assertEquals(2, message.getPackedBoolCount    ());
+    Assert.assertEquals(2, message.getPackedEnumCount   ());
+    Assert.assertEquals(601  , message.getPackedInt32   (0));
+    Assert.assertEquals(602  , message.getPackedInt64   (0));
+    Assert.assertEquals(603  , message.getPackedUint32  (0));
+    Assert.assertEquals(604  , message.getPackedUint64  (0));
+    Assert.assertEquals(605  , message.getPackedSint32  (0));
+    Assert.assertEquals(606  , message.getPackedSint64  (0));
+    Assert.assertEquals(607  , message.getPackedFixed32 (0));
+    Assert.assertEquals(608  , message.getPackedFixed64 (0));
+    Assert.assertEquals(609  , message.getPackedSfixed32(0));
+    Assert.assertEquals(610  , message.getPackedSfixed64(0));
+    Assert.assertEquals(611  , message.getPackedFloat   (0), 0.0);
+    Assert.assertEquals(612  , message.getPackedDouble  (0), 0.0);
+    Assert.assertEquals(true , message.getPackedBool    (0));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+    Assert.assertEquals(701  , message.getPackedInt32   (1));
+    Assert.assertEquals(702  , message.getPackedInt64   (1));
+    Assert.assertEquals(703  , message.getPackedUint32  (1));
+    Assert.assertEquals(704  , message.getPackedUint64  (1));
+    Assert.assertEquals(705  , message.getPackedSint32  (1));
+    Assert.assertEquals(706  , message.getPackedSint64  (1));
+    Assert.assertEquals(707  , message.getPackedFixed32 (1));
+    Assert.assertEquals(708  , message.getPackedFixed64 (1));
+    Assert.assertEquals(709  , message.getPackedSfixed32(1));
+    Assert.assertEquals(710  , message.getPackedSfixed64(1));
+    Assert.assertEquals(711  , message.getPackedFloat   (1), 0.0);
+    Assert.assertEquals(712  , message.getPackedDouble  (1), 0.0);
+    Assert.assertEquals(false, message.getPackedBool    (1));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+  }
+
   // ===================================================================
   // Like above, but for extensions
 
@@ -846,6 +1041,18 @@
   private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
     Assert.assertEquals(a, b);
   }
+  private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a,
+                                            TestAllTypesLite.NestedEnum b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ForeignEnumLite a,
+                                            ForeignEnumLite b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ImportEnumLite a,
+                                            ImportEnumLite b) {
+    Assert.assertEquals(a, b);
+  }
 
   /**
    * Get an unmodifiable {@link ExtensionRegistry} containing all the
@@ -857,12 +1064,23 @@
     return registry.getUnmodifiable();
   }
 
+  public static ExtensionRegistryLite getExtensionRegistryLite() {
+    ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+    registerAllExtensionsLite(registry);
+    return registry.getUnmodifiable();
+  }
+
   /**
-   * Register all of {@code TestAllExtensions}' extensions with the
+   * Register all of {@code TestAllExtensions}'s extensions with the
    * given {@link ExtensionRegistry}.
    */
   public static void registerAllExtensions(ExtensionRegistry registry) {
     UnittestProto.registerAllExtensions(registry);
+    registerAllExtensionsLite(registry);
+  }
+
+  public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+    UnittestLite.registerAllExtensions(registry);
   }
 
   /**
@@ -1509,90 +1727,6 @@
     assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
   }
 
-  /**
-   * Set every field of {@code message} to a unique value.
-   */
-  public static void setPackedFields(TestPackedTypes.Builder message) {
-    message.addPackedInt32   (601);
-    message.addPackedInt64   (602);
-    message.addPackedUint32  (603);
-    message.addPackedUint64  (604);
-    message.addPackedSint32  (605);
-    message.addPackedSint64  (606);
-    message.addPackedFixed32 (607);
-    message.addPackedFixed64 (608);
-    message.addPackedSfixed32(609);
-    message.addPackedSfixed64(610);
-    message.addPackedFloat   (611);
-    message.addPackedDouble  (612);
-    message.addPackedBool    (true);
-    message.addPackedEnum    (ForeignEnum.FOREIGN_BAR);
-    // Add a second one of each field.
-    message.addPackedInt32   (701);
-    message.addPackedInt64   (702);
-    message.addPackedUint32  (703);
-    message.addPackedUint64  (704);
-    message.addPackedSint32  (705);
-    message.addPackedSint64  (706);
-    message.addPackedFixed32 (707);
-    message.addPackedFixed64 (708);
-    message.addPackedSfixed32(709);
-    message.addPackedSfixed64(710);
-    message.addPackedFloat   (711);
-    message.addPackedDouble  (712);
-    message.addPackedBool    (false);
-    message.addPackedEnum    (ForeignEnum.FOREIGN_BAZ);
-  }
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all fields of
-   * {@code message} are set to the values assigned by {@code setPackedFields}.
-   */
-  public static void assertPackedFieldsSet(TestPackedTypes message) {
-    Assert.assertEquals(2, message.getPackedInt32Count   ());
-    Assert.assertEquals(2, message.getPackedInt64Count   ());
-    Assert.assertEquals(2, message.getPackedUint32Count  ());
-    Assert.assertEquals(2, message.getPackedUint64Count  ());
-    Assert.assertEquals(2, message.getPackedSint32Count  ());
-    Assert.assertEquals(2, message.getPackedSint64Count  ());
-    Assert.assertEquals(2, message.getPackedFixed32Count ());
-    Assert.assertEquals(2, message.getPackedFixed64Count ());
-    Assert.assertEquals(2, message.getPackedSfixed32Count());
-    Assert.assertEquals(2, message.getPackedSfixed64Count());
-    Assert.assertEquals(2, message.getPackedFloatCount   ());
-    Assert.assertEquals(2, message.getPackedDoubleCount  ());
-    Assert.assertEquals(2, message.getPackedBoolCount    ());
-    Assert.assertEquals(2, message.getPackedEnumCount   ());
-    Assert.assertEquals(601  , message.getPackedInt32   (0));
-    Assert.assertEquals(602  , message.getPackedInt64   (0));
-    Assert.assertEquals(603  , message.getPackedUint32  (0));
-    Assert.assertEquals(604  , message.getPackedUint64  (0));
-    Assert.assertEquals(605  , message.getPackedSint32  (0));
-    Assert.assertEquals(606  , message.getPackedSint64  (0));
-    Assert.assertEquals(607  , message.getPackedFixed32 (0));
-    Assert.assertEquals(608  , message.getPackedFixed64 (0));
-    Assert.assertEquals(609  , message.getPackedSfixed32(0));
-    Assert.assertEquals(610  , message.getPackedSfixed64(0));
-    Assert.assertEquals(611  , message.getPackedFloat   (0), 0.0);
-    Assert.assertEquals(612  , message.getPackedDouble  (0), 0.0);
-    Assert.assertEquals(true , message.getPackedBool    (0));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
-    Assert.assertEquals(701  , message.getPackedInt32   (1));
-    Assert.assertEquals(702  , message.getPackedInt64   (1));
-    Assert.assertEquals(703  , message.getPackedUint32  (1));
-    Assert.assertEquals(704  , message.getPackedUint64  (1));
-    Assert.assertEquals(705  , message.getPackedSint32  (1));
-    Assert.assertEquals(706  , message.getPackedSint64  (1));
-    Assert.assertEquals(707  , message.getPackedFixed32 (1));
-    Assert.assertEquals(708  , message.getPackedFixed64 (1));
-    Assert.assertEquals(709  , message.getPackedSfixed32(1));
-    Assert.assertEquals(710  , message.getPackedSfixed64(1));
-    Assert.assertEquals(711  , message.getPackedFloat   (1), 0.0);
-    Assert.assertEquals(712  , message.getPackedDouble  (1), 0.0);
-    Assert.assertEquals(false, message.getPackedBool    (1));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
-  }
-
   public static void setPackedExtensions(TestPackedExtensions.Builder message) {
     message.addExtension(packedInt32Extension   , 601);
     message.addExtension(packedInt64Extension   , 602L);
@@ -1672,8 +1806,733 @@
                           message.getExtension(packedEnumExtension, 1));
   }
 
-
   // ===================================================================
+  // Lite extensions
+
+  /**
+   * Set every field of {@code message} to the values expected by
+   * {@code assertAllExtensionsSet()}.
+   */
+  public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
+    message.setExtension(optionalInt32ExtensionLite   , 101);
+    message.setExtension(optionalInt64ExtensionLite   , 102L);
+    message.setExtension(optionalUint32ExtensionLite  , 103);
+    message.setExtension(optionalUint64ExtensionLite  , 104L);
+    message.setExtension(optionalSint32ExtensionLite  , 105);
+    message.setExtension(optionalSint64ExtensionLite  , 106L);
+    message.setExtension(optionalFixed32ExtensionLite , 107);
+    message.setExtension(optionalFixed64ExtensionLite , 108L);
+    message.setExtension(optionalSfixed32ExtensionLite, 109);
+    message.setExtension(optionalSfixed64ExtensionLite, 110L);
+    message.setExtension(optionalFloatExtensionLite   , 111F);
+    message.setExtension(optionalDoubleExtensionLite  , 112D);
+    message.setExtension(optionalBoolExtensionLite    , true);
+    message.setExtension(optionalStringExtensionLite  , "115");
+    message.setExtension(optionalBytesExtensionLite   , toBytes("116"));
+
+    message.setExtension(optionalGroupExtensionLite,
+      OptionalGroup_extension_lite.newBuilder().setA(117).build());
+    message.setExtension(optionalNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+    message.setExtension(optionalForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(119).build());
+    message.setExtension(optionalImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(120).build());
+
+    message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+    message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+    message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+    message.setExtension(optionalStringPieceExtensionLite, "124");
+    message.setExtension(optionalCordExtensionLite, "125");
+
+    // -----------------------------------------------------------------
+
+    message.addExtension(repeatedInt32ExtensionLite   , 201);
+    message.addExtension(repeatedInt64ExtensionLite   , 202L);
+    message.addExtension(repeatedUint32ExtensionLite  , 203);
+    message.addExtension(repeatedUint64ExtensionLite  , 204L);
+    message.addExtension(repeatedSint32ExtensionLite  , 205);
+    message.addExtension(repeatedSint64ExtensionLite  , 206L);
+    message.addExtension(repeatedFixed32ExtensionLite , 207);
+    message.addExtension(repeatedFixed64ExtensionLite , 208L);
+    message.addExtension(repeatedSfixed32ExtensionLite, 209);
+    message.addExtension(repeatedSfixed64ExtensionLite, 210L);
+    message.addExtension(repeatedFloatExtensionLite   , 211F);
+    message.addExtension(repeatedDoubleExtensionLite  , 212D);
+    message.addExtension(repeatedBoolExtensionLite    , true);
+    message.addExtension(repeatedStringExtensionLite  , "215");
+    message.addExtension(repeatedBytesExtensionLite   , toBytes("216"));
+
+    message.addExtension(repeatedGroupExtensionLite,
+      RepeatedGroup_extension_lite.newBuilder().setA(217).build());
+    message.addExtension(repeatedNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+    message.addExtension(repeatedForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(219).build());
+    message.addExtension(repeatedImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(220).build());
+
+    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
+    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
+
+    message.addExtension(repeatedStringPieceExtensionLite, "224");
+    message.addExtension(repeatedCordExtensionLite, "225");
+
+    // Add a second one of each field.
+    message.addExtension(repeatedInt32ExtensionLite   , 301);
+    message.addExtension(repeatedInt64ExtensionLite   , 302L);
+    message.addExtension(repeatedUint32ExtensionLite  , 303);
+    message.addExtension(repeatedUint64ExtensionLite  , 304L);
+    message.addExtension(repeatedSint32ExtensionLite  , 305);
+    message.addExtension(repeatedSint64ExtensionLite  , 306L);
+    message.addExtension(repeatedFixed32ExtensionLite , 307);
+    message.addExtension(repeatedFixed64ExtensionLite , 308L);
+    message.addExtension(repeatedSfixed32ExtensionLite, 309);
+    message.addExtension(repeatedSfixed64ExtensionLite, 310L);
+    message.addExtension(repeatedFloatExtensionLite   , 311F);
+    message.addExtension(repeatedDoubleExtensionLite  , 312D);
+    message.addExtension(repeatedBoolExtensionLite    , false);
+    message.addExtension(repeatedStringExtensionLite  , "315");
+    message.addExtension(repeatedBytesExtensionLite   , toBytes("316"));
+
+    message.addExtension(repeatedGroupExtensionLite,
+      RepeatedGroup_extension_lite.newBuilder().setA(317).build());
+    message.addExtension(repeatedNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+    message.addExtension(repeatedForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(319).build());
+    message.addExtension(repeatedImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(320).build());
+
+    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+    message.addExtension(repeatedStringPieceExtensionLite, "324");
+    message.addExtension(repeatedCordExtensionLite, "325");
+
+    // -----------------------------------------------------------------
+
+    message.setExtension(defaultInt32ExtensionLite   , 401);
+    message.setExtension(defaultInt64ExtensionLite   , 402L);
+    message.setExtension(defaultUint32ExtensionLite  , 403);
+    message.setExtension(defaultUint64ExtensionLite  , 404L);
+    message.setExtension(defaultSint32ExtensionLite  , 405);
+    message.setExtension(defaultSint64ExtensionLite  , 406L);
+    message.setExtension(defaultFixed32ExtensionLite , 407);
+    message.setExtension(defaultFixed64ExtensionLite , 408L);
+    message.setExtension(defaultSfixed32ExtensionLite, 409);
+    message.setExtension(defaultSfixed64ExtensionLite, 410L);
+    message.setExtension(defaultFloatExtensionLite   , 411F);
+    message.setExtension(defaultDoubleExtensionLite  , 412D);
+    message.setExtension(defaultBoolExtensionLite    , false);
+    message.setExtension(defaultStringExtensionLite  , "415");
+    message.setExtension(defaultBytesExtensionLite   , toBytes("416"));
+
+    message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
+    message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
+    message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
+
+    message.setExtension(defaultStringPieceExtensionLite, "424");
+    message.setExtension(defaultCordExtensionLite, "425");
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Modify the repeated extensions of {@code message} to contain the values
+   * expected by {@code assertRepeatedExtensionsModified()}.
+   */
+  public static void modifyRepeatedExtensions(
+      TestAllExtensionsLite.Builder message) {
+    message.setExtension(repeatedInt32ExtensionLite   , 1, 501);
+    message.setExtension(repeatedInt64ExtensionLite   , 1, 502L);
+    message.setExtension(repeatedUint32ExtensionLite  , 1, 503);
+    message.setExtension(repeatedUint64ExtensionLite  , 1, 504L);
+    message.setExtension(repeatedSint32ExtensionLite  , 1, 505);
+    message.setExtension(repeatedSint64ExtensionLite  , 1, 506L);
+    message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
+    message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
+    message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
+    message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
+    message.setExtension(repeatedFloatExtensionLite   , 1, 511F);
+    message.setExtension(repeatedDoubleExtensionLite  , 1, 512D);
+    message.setExtension(repeatedBoolExtensionLite    , 1, true);
+    message.setExtension(repeatedStringExtensionLite  , 1, "515");
+    message.setExtension(repeatedBytesExtensionLite   , 1, toBytes("516"));
+
+    message.setExtension(repeatedGroupExtensionLite, 1,
+      RepeatedGroup_extension_lite.newBuilder().setA(517).build());
+    message.setExtension(repeatedNestedMessageExtensionLite, 1,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
+    message.setExtension(repeatedForeignMessageExtensionLite, 1,
+      ForeignMessageLite.newBuilder().setC(519).build());
+    message.setExtension(repeatedImportMessageExtensionLite, 1,
+      ImportMessageLite.newBuilder().setD(520).build());
+
+    message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
+    message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
+    message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
+
+    message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
+    message.setExtension(repeatedCordExtensionLite, 1, "525");
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are set to the values assigned by {@code setAllExtensions}.
+   */
+  public static void assertAllExtensionsSet(TestAllExtensionsLite message) {
+    Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite    ));
+    Assert.assertTrue(message.hasExtension(optionalStringExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite   ));
+
+    Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite         ));
+    Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite ));
+
+    Assert.assertTrue(message.getExtension(optionalGroupExtensionLite         ).hasA());
+    Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+    Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+    Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+    Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite ));
+
+    Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalCordExtensionLite));
+
+    assertEqualsExactType(101  , message.getExtension(optionalInt32ExtensionLite   ));
+    assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite   ));
+    assertEqualsExactType(103  , message.getExtension(optionalUint32ExtensionLite  ));
+    assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite  ));
+    assertEqualsExactType(105  , message.getExtension(optionalSint32ExtensionLite  ));
+    assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite  ));
+    assertEqualsExactType(107  , message.getExtension(optionalFixed32ExtensionLite ));
+    assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite ));
+    assertEqualsExactType(109  , message.getExtension(optionalSfixed32ExtensionLite));
+    assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite));
+    assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite   ));
+    assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite  ));
+    assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite    ));
+    assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite  ));
+    assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite));
+
+    assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite         ).getA());
+    assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+    assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
+    assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+      message.getExtension(optionalNestedEnumExtensionLite));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+      message.getExtension(optionalForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+      message.getExtension(optionalImportEnumExtensionLite));
+
+    assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite));
+    assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite   ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite         ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+    assertEqualsExactType(201  , message.getExtension(repeatedInt32ExtensionLite   , 0));
+    assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite   , 0));
+    assertEqualsExactType(203  , message.getExtension(repeatedUint32ExtensionLite  , 0));
+    assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite  , 0));
+    assertEqualsExactType(205  , message.getExtension(repeatedSint32ExtensionLite  , 0));
+    assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite  , 0));
+    assertEqualsExactType(207  , message.getExtension(repeatedFixed32ExtensionLite , 0));
+    assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite   , 0));
+    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite  , 0));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite    , 0));
+    assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite  , 0));
+    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+    assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite         ,0).getA());
+    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+      message.getExtension(repeatedNestedEnumExtensionLite, 0));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+      message.getExtension(repeatedForeignEnumExtensionLite, 0));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+      message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+    assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+    assertEqualsExactType(301  , message.getExtension(repeatedInt32ExtensionLite   , 1));
+    assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite   , 1));
+    assertEqualsExactType(303  , message.getExtension(repeatedUint32ExtensionLite  , 1));
+    assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite  , 1));
+    assertEqualsExactType(305  , message.getExtension(repeatedSint32ExtensionLite  , 1));
+    assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite  , 1));
+    assertEqualsExactType(307  , message.getExtension(repeatedFixed32ExtensionLite , 1));
+    assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+    assertEqualsExactType(309  , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+    assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+    assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite   , 1));
+    assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite  , 1));
+    assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite    , 1));
+    assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite  , 1));
+    assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+    assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite         ,1).getA());
+    assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+    assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+    assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+      message.getExtension(repeatedNestedEnumExtensionLite, 1));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+      message.getExtension(repeatedForeignEnumExtensionLite, 1));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+      message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+    assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1));
+    assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite    ));
+    Assert.assertTrue(message.hasExtension(defaultStringExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite   ));
+
+    Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite ));
+    Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite ));
+
+    Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultCordExtensionLite));
+
+    assertEqualsExactType(401  , message.getExtension(defaultInt32ExtensionLite   ));
+    assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite   ));
+    assertEqualsExactType(403  , message.getExtension(defaultUint32ExtensionLite  ));
+    assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite  ));
+    assertEqualsExactType(405  , message.getExtension(defaultSint32ExtensionLite  ));
+    assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite  ));
+    assertEqualsExactType(407  , message.getExtension(defaultFixed32ExtensionLite ));
+    assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite ));
+    assertEqualsExactType(409  , message.getExtension(defaultSfixed32ExtensionLite));
+    assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite));
+    assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite   ));
+    assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite  ));
+    assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite    ));
+    assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite  ));
+    assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite));
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+      message.getExtension(defaultNestedEnumExtensionLite ));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+      message.getExtension(defaultForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+      message.getExtension(defaultImportEnumExtensionLite));
+
+    assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite));
+    assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are cleared, and that getting the extensions returns their
+   * default values.
+   */
+  public static void assertExtensionsClear(TestAllExtensionsLite message) {
+    // hasBlah() should initially be false for all optional fields.
+    Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite    ));
+    Assert.assertFalse(message.hasExtension(optionalStringExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite   ));
+
+    Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite         ));
+    Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+
+    Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite ));
+
+    Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalCordExtensionLite));
+
+    // Optional fields without defaults are set to zero or something like it.
+    assertEqualsExactType(0    , message.getExtension(optionalInt32ExtensionLite   ));
+    assertEqualsExactType(0L   , message.getExtension(optionalInt64ExtensionLite   ));
+    assertEqualsExactType(0    , message.getExtension(optionalUint32ExtensionLite  ));
+    assertEqualsExactType(0L   , message.getExtension(optionalUint64ExtensionLite  ));
+    assertEqualsExactType(0    , message.getExtension(optionalSint32ExtensionLite  ));
+    assertEqualsExactType(0L   , message.getExtension(optionalSint64ExtensionLite  ));
+    assertEqualsExactType(0    , message.getExtension(optionalFixed32ExtensionLite ));
+    assertEqualsExactType(0L   , message.getExtension(optionalFixed64ExtensionLite ));
+    assertEqualsExactType(0    , message.getExtension(optionalSfixed32ExtensionLite));
+    assertEqualsExactType(0L   , message.getExtension(optionalSfixed64ExtensionLite));
+    assertEqualsExactType(0F   , message.getExtension(optionalFloatExtensionLite   ));
+    assertEqualsExactType(0D   , message.getExtension(optionalDoubleExtensionLite  ));
+    assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite    ));
+    assertEqualsExactType(""   , message.getExtension(optionalStringExtensionLite  ));
+    assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
+
+    // Embedded messages should also be clear.
+    Assert.assertFalse(message.getExtension(optionalGroupExtensionLite         ).hasA());
+    Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+    Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+    Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+    assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite         ).getA());
+    assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+    assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
+    assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+
+    // Enums without defaults are set to the first value in the enum.
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+      message.getExtension(optionalNestedEnumExtensionLite ));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+      message.getExtension(optionalForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+      message.getExtension(optionalImportEnumExtensionLite));
+
+    assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite));
+    assertEqualsExactType("", message.getExtension(optionalCordExtensionLite));
+
+    // Repeated fields are empty.
+    Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite    ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite   ));
+
+    Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite         ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
+
+    Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite));
+
+    // hasBlah() should also be false for all default fields.
+    Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite    ));
+    Assert.assertFalse(message.hasExtension(defaultStringExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite   ));
+
+    Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite ));
+    Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite ));
+
+    Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultCordExtensionLite));
+
+    // Fields with defaults have their default values (duh).
+    assertEqualsExactType( 41    , message.getExtension(defaultInt32ExtensionLite   ));
+    assertEqualsExactType( 42L   , message.getExtension(defaultInt64ExtensionLite   ));
+    assertEqualsExactType( 43    , message.getExtension(defaultUint32ExtensionLite  ));
+    assertEqualsExactType( 44L   , message.getExtension(defaultUint64ExtensionLite  ));
+    assertEqualsExactType(-45    , message.getExtension(defaultSint32ExtensionLite  ));
+    assertEqualsExactType( 46L   , message.getExtension(defaultSint64ExtensionLite  ));
+    assertEqualsExactType( 47    , message.getExtension(defaultFixed32ExtensionLite ));
+    assertEqualsExactType( 48L   , message.getExtension(defaultFixed64ExtensionLite ));
+    assertEqualsExactType( 49    , message.getExtension(defaultSfixed32ExtensionLite));
+    assertEqualsExactType(-50L   , message.getExtension(defaultSfixed64ExtensionLite));
+    assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite   ));
+    assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite  ));
+    assertEqualsExactType(true   , message.getExtension(defaultBoolExtensionLite    ));
+    assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite  ));
+    assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite));
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+      message.getExtension(defaultNestedEnumExtensionLite ));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+      message.getExtension(defaultForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+      message.getExtension(defaultImportEnumExtensionLite));
+
+    assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite));
+    assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are set to the values assigned by {@code setAllExtensions}
+   * followed by {@code modifyRepeatedExtensions}.
+   */
+  public static void assertRepeatedExtensionsModified(
+      TestAllExtensionsLite message) {
+    // ModifyRepeatedFields only sets the second repeated element of each
+    // field.  In addition to verifying this, we also verify that the first
+    // element and size were *not* modified.
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite   ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite         ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+    assertEqualsExactType(201  , message.getExtension(repeatedInt32ExtensionLite   , 0));
+    assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite   , 0));
+    assertEqualsExactType(203  , message.getExtension(repeatedUint32ExtensionLite  , 0));
+    assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite  , 0));
+    assertEqualsExactType(205  , message.getExtension(repeatedSint32ExtensionLite  , 0));
+    assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite  , 0));
+    assertEqualsExactType(207  , message.getExtension(repeatedFixed32ExtensionLite , 0));
+    assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite   , 0));
+    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite  , 0));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite    , 0));
+    assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite  , 0));
+    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+    assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite         ,0).getA());
+    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+      message.getExtension(repeatedNestedEnumExtensionLite, 0));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+      message.getExtension(repeatedForeignEnumExtensionLite, 0));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+      message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+    assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+    // Actually verify the second (modified) elements now.
+    assertEqualsExactType(501  , message.getExtension(repeatedInt32ExtensionLite   , 1));
+    assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite   , 1));
+    assertEqualsExactType(503  , message.getExtension(repeatedUint32ExtensionLite  , 1));
+    assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite  , 1));
+    assertEqualsExactType(505  , message.getExtension(repeatedSint32ExtensionLite  , 1));
+    assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite  , 1));
+    assertEqualsExactType(507  , message.getExtension(repeatedFixed32ExtensionLite , 1));
+    assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+    assertEqualsExactType(509  , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+    assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+    assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite   , 1));
+    assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite  , 1));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite    , 1));
+    assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite  , 1));
+    assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+    assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite         ,1).getA());
+    assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+    assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+    assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+      message.getExtension(repeatedNestedEnumExtensionLite, 1));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+      message.getExtension(repeatedForeignEnumExtensionLite, 1));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+      message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+    assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1));
+    assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1));
+  }
+
+  public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
+    message.addExtension(packedInt32ExtensionLite   , 601);
+    message.addExtension(packedInt64ExtensionLite   , 602L);
+    message.addExtension(packedUint32ExtensionLite  , 603);
+    message.addExtension(packedUint64ExtensionLite  , 604L);
+    message.addExtension(packedSint32ExtensionLite  , 605);
+    message.addExtension(packedSint64ExtensionLite  , 606L);
+    message.addExtension(packedFixed32ExtensionLite , 607);
+    message.addExtension(packedFixed64ExtensionLite , 608L);
+    message.addExtension(packedSfixed32ExtensionLite, 609);
+    message.addExtension(packedSfixed64ExtensionLite, 610L);
+    message.addExtension(packedFloatExtensionLite   , 611F);
+    message.addExtension(packedDoubleExtensionLite  , 612D);
+    message.addExtension(packedBoolExtensionLite    , true);
+    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+    // Add a second one of each field.
+    message.addExtension(packedInt32ExtensionLite   , 701);
+    message.addExtension(packedInt64ExtensionLite   , 702L);
+    message.addExtension(packedUint32ExtensionLite  , 703);
+    message.addExtension(packedUint64ExtensionLite  , 704L);
+    message.addExtension(packedSint32ExtensionLite  , 705);
+    message.addExtension(packedSint64ExtensionLite  , 706L);
+    message.addExtension(packedFixed32ExtensionLite , 707);
+    message.addExtension(packedFixed64ExtensionLite , 708L);
+    message.addExtension(packedSfixed32ExtensionLite, 709);
+    message.addExtension(packedSfixed64ExtensionLite, 710L);
+    message.addExtension(packedFloatExtensionLite   , 711F);
+    message.addExtension(packedDoubleExtensionLite  , 712D);
+    message.addExtension(packedBoolExtensionLite    , false);
+    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+  }
+
+  public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) {
+    Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite));
+    assertEqualsExactType(601  , message.getExtension(packedInt32ExtensionLite   , 0));
+    assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite   , 0));
+    assertEqualsExactType(603  , message.getExtension(packedUint32ExtensionLite  , 0));
+    assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite  , 0));
+    assertEqualsExactType(605  , message.getExtension(packedSint32ExtensionLite  , 0));
+    assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite  , 0));
+    assertEqualsExactType(607  , message.getExtension(packedFixed32ExtensionLite , 0));
+    assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0));
+    assertEqualsExactType(609  , message.getExtension(packedSfixed32ExtensionLite, 0));
+    assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0));
+    assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite   , 0));
+    assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite  , 0));
+    assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite    , 0));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+                          message.getExtension(packedEnumExtensionLite, 0));
+    assertEqualsExactType(701  , message.getExtension(packedInt32ExtensionLite   , 1));
+    assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite   , 1));
+    assertEqualsExactType(703  , message.getExtension(packedUint32ExtensionLite  , 1));
+    assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite  , 1));
+    assertEqualsExactType(705  , message.getExtension(packedSint32ExtensionLite  , 1));
+    assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite  , 1));
+    assertEqualsExactType(707  , message.getExtension(packedFixed32ExtensionLite , 1));
+    assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1));
+    assertEqualsExactType(709  , message.getExtension(packedSfixed32ExtensionLite, 1));
+    assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1));
+    assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite   , 1));
+    assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite  , 1));
+    assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite    , 1));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+                          message.getExtension(packedEnumExtensionLite, 1));
+  }
+
+  // =================================================================
 
   /**
    * Performs the same things that the methods of {@code TestUtil} do, but
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index ec4910a..1d73165 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -30,9 +30,12 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestProto.OneString;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
 import protobuf_unittest.UnittestMset.TestMessageSet;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
@@ -173,6 +176,22 @@
       TextFormat.printToString(message));
   }
 
+  public void testPrintField() throws Exception {
+    final FieldDescriptor dataField =
+      OneString.getDescriptor().findFieldByName("data");
+    assertEquals(
+      "data: \"test data\"\n",
+      TextFormat.printFieldToString(dataField, "test data"));
+
+    final FieldDescriptor optionalField =
+      TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+    final Object value = NestedMessage.newBuilder().setBb(42).build();
+    
+    assertEquals(
+      "optional_nested_message {\n  bb: 42\n}\n",
+      TextFormat.printFieldToString(optionalField, value));
+  }
+  
   /**
    * Helper to construct a ByteString from a String containing only 8-bit
    * characters.  The characters are converted directly to bytes, *not*
@@ -450,21 +469,21 @@
     try {
       TextFormat.unescapeText("\\x");
       fail("Should have thrown an exception.");
-    } catch (TextFormat.InvalidEscapeSequence e) {
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
     }
 
     try {
       TextFormat.unescapeText("\\z");
       fail("Should have thrown an exception.");
-    } catch (TextFormat.InvalidEscapeSequence e) {
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
     }
 
     try {
       TextFormat.unescapeText("\\");
       fail("Should have thrown an exception.");
-    } catch (TextFormat.InvalidEscapeSequence e) {
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
     }
   }
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 4afefdb..bd1c6db 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -45,6 +45,8 @@
 import protobuf_unittest.UnittestMset.RawMessageSet;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
 
 /**
  * Tests related to parsing and serialization.
@@ -100,6 +102,32 @@
     assertEquals(rawBytes, rawBytes2);
   }
 
+  public void testSerializeExtensionsLite() throws Exception {
+    // TestAllTypes and TestAllExtensions should have compatible wire formats,
+    // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+    // it should work.
+
+    TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+    assertEquals(rawBytes.size(), message.getSerializedSize());
+
+    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+    TestUtil.assertAllFieldsSet(message2);
+  }
+
+  public void testSerializePackedExtensionsLite() throws Exception {
+    // TestPackedTypes and TestPackedExtensions should have compatible wire
+    // formats; check that they serialize to the same string.
+    TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+
+    TestPackedTypes message2 = TestUtil.getPackedSet();
+    ByteString rawBytes2 = message2.toByteString();
+
+    assertEquals(rawBytes, rawBytes2);
+  }
+
   public void testParseExtensions() throws Exception {
     // TestAllTypes and TestAllExtensions should have compatible wire formats,
     // so if we serialize a TestAllTypes then parse it as TestAllExtensions
@@ -129,6 +157,43 @@
     TestUtil.assertPackedExtensionsSet(message2);
   }
 
+  public void testParseExtensionsLite() throws Exception {
+    // TestAllTypes and TestAllExtensions should have compatible wire formats,
+    // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+    // it should work.
+
+    TestAllTypes message = TestUtil.getAllSet();
+    ByteString rawBytes = message.toByteString();
+
+    ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
+
+    TestAllExtensionsLite message2 =
+      TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
+
+    TestUtil.assertAllExtensionsSet(message2);
+
+    // Try again using a full extension registry.
+    ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+    TestAllExtensionsLite message3 =
+      TestAllExtensionsLite.parseFrom(rawBytes, registry);
+
+    TestUtil.assertAllExtensionsSet(message3);
+  }
+
+  public void testParsePackedExtensionsLite() throws Exception {
+    // Ensure that packed extensions can be properly parsed.
+    TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+
+    ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
+
+    TestPackedExtensionsLite message2 =
+        TestPackedExtensionsLite.parseFrom(rawBytes, registry);
+
+    TestUtil.assertPackedExtensionsSet(message2);
+  }
+
   public void testExtensionsSerializedSize() throws Exception {
     assertEquals(TestUtil.getAllSet().getSerializedSize(),
                  TestUtil.getAllExtensionsSet().getSerializedSize());
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index fa1e340..d8a825d 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -112,9 +112,11 @@
       return
 
     orig_empty = len(self._values) == 0
+    new_values = []
     for elem in elem_seq:
       self._type_checker.CheckValue(elem)
-    self._values.extend(elem_seq)
+      new_values.append(elem)
+    self._values.extend(new_values)
     self._message_listener.ByteSizeDirty()
     if orig_empty:
       self._message_listener.TransitionToNonempty()
@@ -139,9 +141,11 @@
 
   def __setslice__(self, start, stop, values):
     """Sets the subset of items from between the specified indices."""
+    new_values = []
     for value in values:
       self._type_checker.CheckValue(value)
-    self._values[start:stop] = list(values)
+      new_values.append(value)
+    self._values[start:stop] = new_values
     self._message_listener.ByteSizeDirty()
 
   def __delitem__(self, key):
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index 0bee610..83d6fe0 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -135,12 +135,12 @@
   def ReadFloat(self):
     """Reads and returns a 4-byte floating-point number."""
     serialized = self._stream.ReadBytes(4)
-    return struct.unpack('f', serialized)[0]
+    return struct.unpack(wire_format.FORMAT_FLOAT_LITTLE_ENDIAN, serialized)[0]
 
   def ReadDouble(self):
     """Reads and returns an 8-byte floating-point number."""
     serialized = self._stream.ReadBytes(8)
-    return struct.unpack('d', serialized)[0]
+    return struct.unpack(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, serialized)[0]
 
   def ReadBool(self):
     """Reads and returns a bool."""
diff --git a/python/google/protobuf/internal/decoder_test.py b/python/google/protobuf/internal/decoder_test.py
index 9bae888..98e4647 100755
--- a/python/google/protobuf/internal/decoder_test.py
+++ b/python/google/protobuf/internal/decoder_test.py
@@ -36,12 +36,12 @@
 
 import struct
 import unittest
-from google.protobuf.internal import wire_format
-from google.protobuf.internal import encoder
 from google.protobuf.internal import decoder
-import logging
+from google.protobuf.internal import encoder
 from google.protobuf.internal import input_stream
+from google.protobuf.internal import wire_format
 from google.protobuf import message
+import logging
 import mox
 
 
@@ -110,6 +110,10 @@
     self.mox.VerifyAll()
     self.mox.ResetAll()
 
+  VAL = 1.125  # Perfectly representable as a float (no rounding error).
+  LITTLE_FLOAT_VAL = '\x00\x00\x90?'
+  LITTLE_DOUBLE_VAL = '\x00\x00\x00\x00\x00\x00\xf2?'
+
   def testReadScalars(self):
     test_string = 'I can feel myself getting sutpider.'
     scalar_tests = [
@@ -125,10 +129,10 @@
          'ReadLittleEndian32', long(0xffffffff)],
         ['sfixed64', decoder.Decoder.ReadSFixed64, long(-1),
          'ReadLittleEndian64', 0xffffffffffffffff],
-        ['float', decoder.Decoder.ReadFloat, 0.0,
-         'ReadBytes', struct.pack('f', 0.0), 4],
-        ['double', decoder.Decoder.ReadDouble, 0.0,
-         'ReadBytes', struct.pack('d', 0.0), 8],
+        ['float', decoder.Decoder.ReadFloat, self.VAL,
+         'ReadBytes', self.LITTLE_FLOAT_VAL, 4],
+        ['double', decoder.Decoder.ReadDouble, self.VAL,
+         'ReadBytes', self.LITTLE_DOUBLE_VAL, 8],
         ['bool', decoder.Decoder.ReadBool, True, 'ReadVarUInt32', 1],
         ['enum', decoder.Decoder.ReadEnum, 23, 'ReadVarUInt32', 23],
         ['string', decoder.Decoder.ReadString,
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index eed8c8b..3ec3b2b 100755
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -123,11 +123,13 @@
 
   def AppendFloatNoTag(self, value):
     """Appends a floating-point number to our buffer."""
-    self._stream.AppendRawBytes(struct.pack('f', value))
+    self._stream.AppendRawBytes(
+        struct.pack(wire_format.FORMAT_FLOAT_LITTLE_ENDIAN, value))
 
   def AppendDoubleNoTag(self, value):
     """Appends a double-precision floating-point number to our buffer."""
-    self._stream.AppendRawBytes(struct.pack('d', value))
+    self._stream.AppendRawBytes(
+        struct.pack(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, value))
 
   def AppendBoolNoTag(self, value):
     """Appends a boolean to our buffer."""
diff --git a/python/google/protobuf/internal/encoder_test.py b/python/google/protobuf/internal/encoder_test.py
index 83a21c3..bf75ea8 100755
--- a/python/google/protobuf/internal/encoder_test.py
+++ b/python/google/protobuf/internal/encoder_test.py
@@ -123,6 +123,10 @@
     self.mox.VerifyAll()
     self.mox.ResetAll()
 
+  VAL = 1.125  # Perfectly representable as a float (no rounding error).
+  LITTLE_FLOAT_VAL = '\x00\x00\x90?'
+  LITTLE_DOUBLE_VAL = '\x00\x00\x00\x00\x00\x00\xf2?'
+
   def testAppendScalars(self):
     utf8_bytes = '\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'
     utf8_string = unicode(utf8_bytes, 'utf-8')
@@ -144,9 +148,9 @@
         ['sfixed64', self.encoder.AppendSFixed64, 'AppendLittleEndian64',
          wire_format.WIRETYPE_FIXED64, -1, 0xffffffffffffffff],
         ['float', self.encoder.AppendFloat, 'AppendRawBytes',
-         wire_format.WIRETYPE_FIXED32, 0.0, struct.pack('f', 0.0)],
+         wire_format.WIRETYPE_FIXED32, self.VAL, self.LITTLE_FLOAT_VAL],
         ['double', self.encoder.AppendDouble, 'AppendRawBytes',
-         wire_format.WIRETYPE_FIXED64, 0.0, struct.pack('d', 0.0)],
+         wire_format.WIRETYPE_FIXED64, self.VAL, self.LITTLE_DOUBLE_VAL],
         ['bool', self.encoder.AppendBool, 'AppendVarint32',
          wire_format.WIRETYPE_VARINT, False],
         ['enum', self.encoder.AppendEnum, 'AppendVarint32',
@@ -185,9 +189,9 @@
         ['sfixed64', self.encoder.AppendSFixed64NoTag,
          'AppendLittleEndian64', None, 0],
         ['float', self.encoder.AppendFloatNoTag,
-         'AppendRawBytes', None, 0.0, struct.pack('f', 0.0)],
+         'AppendRawBytes', None, self.VAL, self.LITTLE_FLOAT_VAL],
         ['double', self.encoder.AppendDoubleNoTag,
-         'AppendRawBytes', None, 0.0, struct.pack('d', 0.0)],
+         'AppendRawBytes', None, self.VAL, self.LITTLE_DOUBLE_VAL],
         ['bool', self.encoder.AppendBoolNoTag, 'AppendVarint32', None, 0],
         ['enum', self.encoder.AppendEnumNoTag, 'AppendVarint32', None, 0],
         ['sint32', self.encoder.AppendSInt32NoTag,
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
new file mode 100755
index 0000000..df344cf
--- /dev/null
+++ b/python/google/protobuf/internal/message_test.py
@@ -0,0 +1,53 @@
+#! /usr/bin/python
+#
+# 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.
+
+"""Tests python protocol buffers against the golden message."""
+
+__author__ = 'gps@google.com (Gregory P. Smith)'
+
+import unittest
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf.internal import test_util
+
+
+class MessageTest(test_util.GoldenMessageTestCase):
+
+  def testGoldenMessage(self):
+    golden_data = test_util.GoldenFile('golden_message').read()
+    golden_message = unittest_pb2.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.ExpectAllFieldsSet(golden_message)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index e2da769..8610177 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -232,13 +232,14 @@
     proto.repeated_string.extend(['foo', 'bar'])
     proto.repeated_string.extend([])
     proto.repeated_string.append('baz')
+    proto.repeated_string.extend(str(x) for x in xrange(2))
     proto.optional_int32 = 21
     self.assertEqual(
       [ (proto.DESCRIPTOR.fields_by_name['optional_int32'  ], 21),
         (proto.DESCRIPTOR.fields_by_name['repeated_int32'  ], [5, 11]),
         (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]),
         (proto.DESCRIPTOR.fields_by_name['repeated_string' ],
-          ['foo', 'bar', 'baz']) ],
+          ['foo', 'bar', 'baz', '0', '1']) ],
       proto.ListFields())
 
   def testSingularListExtensions(self):
@@ -447,6 +448,10 @@
     self.assertEqual([25, 20, 15], proto.repeated_int32[1:4])
     self.assertEqual([5, 25, 20, 15, 30], proto.repeated_int32[:])
 
+    # Test slice assignment with an iterator
+    proto.repeated_int32[1:4] = (i for i in xrange(3))
+    self.assertEqual([5, 0, 1, 2, 30], proto.repeated_int32)
+
     # Test slice assignment.
     proto.repeated_int32[1:4] = [35, 40, 45]
     self.assertEqual([5, 35, 40, 45, 30], proto.repeated_int32)
@@ -1739,13 +1744,14 @@
     self.assertEqual(2, proto2.b)
     self.assertEqual(3, proto2.c)
 
-  def testSerializedAllPackedFields(self):
+  def testSerializeAllPackedFields(self):
     first_proto = unittest_pb2.TestPackedTypes()
     second_proto = unittest_pb2.TestPackedTypes()
     test_util.SetAllPackedFields(first_proto)
     serialized = first_proto.SerializeToString()
     self.assertEqual(first_proto.ByteSize(), len(serialized))
-    second_proto.MergeFromString(serialized)
+    bytes_read = second_proto.MergeFromString(serialized)
+    self.assertEqual(second_proto.ByteSize(), bytes_read)
     self.assertEqual(first_proto, second_proto)
 
   def testSerializeAllPackedExtensions(self):
@@ -1753,7 +1759,8 @@
     second_proto = unittest_pb2.TestPackedExtensions()
     test_util.SetAllPackedExtensions(first_proto)
     serialized = first_proto.SerializeToString()
-    second_proto.MergeFromString(serialized)
+    bytes_read = second_proto.MergeFromString(serialized)
+    self.assertEqual(second_proto.ByteSize(), bytes_read)
     self.assertEqual(first_proto, second_proto)
 
   def testMergePackedFromStringWhenSomeFieldsAlreadySet(self):
@@ -1838,6 +1845,79 @@
     self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER,
       51)
 
+  def testInitKwargs(self):
+    proto = unittest_pb2.TestAllTypes(
+        optional_int32=1,
+        optional_string='foo',
+        optional_bool=True,
+        optional_bytes='bar',
+        optional_nested_message=unittest_pb2.TestAllTypes.NestedMessage(bb=1),
+        optional_foreign_message=unittest_pb2.ForeignMessage(c=1),
+        optional_nested_enum=unittest_pb2.TestAllTypes.FOO,
+        optional_foreign_enum=unittest_pb2.FOREIGN_FOO,
+        repeated_int32=[1, 2, 3])
+    self.assertTrue(proto.IsInitialized())
+    self.assertTrue(proto.HasField('optional_int32'))
+    self.assertTrue(proto.HasField('optional_string'))
+    self.assertTrue(proto.HasField('optional_bool'))
+    self.assertTrue(proto.HasField('optional_bytes'))
+    self.assertTrue(proto.HasField('optional_nested_message'))
+    self.assertTrue(proto.HasField('optional_foreign_message'))
+    self.assertTrue(proto.HasField('optional_nested_enum'))
+    self.assertTrue(proto.HasField('optional_foreign_enum'))
+    self.assertEqual(1, proto.optional_int32)
+    self.assertEqual('foo', proto.optional_string)
+    self.assertEqual(True, proto.optional_bool)
+    self.assertEqual('bar', proto.optional_bytes)
+    self.assertEqual(1, proto.optional_nested_message.bb)
+    self.assertEqual(1, proto.optional_foreign_message.c)
+    self.assertEqual(unittest_pb2.TestAllTypes.FOO,
+                     proto.optional_nested_enum)
+    self.assertEqual(unittest_pb2.FOREIGN_FOO, proto.optional_foreign_enum)
+    self.assertEqual([1, 2, 3], proto.repeated_int32)
+
+  def testInitArgsUnknownFieldName(self):
+    def InitalizeEmptyMessageWithExtraKeywordArg():
+      unused_proto = unittest_pb2.TestEmptyMessage(unknown='unknown')
+    self._CheckRaises(ValueError,
+                      InitalizeEmptyMessageWithExtraKeywordArg,
+                      'Protocol message has no "unknown" field.')
+
+  def testInitRequiredKwargs(self):
+    proto = unittest_pb2.TestRequired(a=1, b=1, c=1)
+    self.assertTrue(proto.IsInitialized())
+    self.assertTrue(proto.HasField('a'))
+    self.assertTrue(proto.HasField('b'))
+    self.assertTrue(proto.HasField('c'))
+    self.assertTrue(not proto.HasField('dummy2'))
+    self.assertEqual(1, proto.a)
+    self.assertEqual(1, proto.b)
+    self.assertEqual(1, proto.c)
+
+  def testInitRequiredForeignKwargs(self):
+    proto = unittest_pb2.TestRequiredForeign(
+        optional_message=unittest_pb2.TestRequired(a=1, b=1, c=1))
+    self.assertTrue(proto.IsInitialized())
+    self.assertTrue(proto.HasField('optional_message'))
+    self.assertTrue(proto.optional_message.IsInitialized())
+    self.assertTrue(proto.optional_message.HasField('a'))
+    self.assertTrue(proto.optional_message.HasField('b'))
+    self.assertTrue(proto.optional_message.HasField('c'))
+    self.assertTrue(not proto.optional_message.HasField('dummy2'))
+    self.assertEqual(unittest_pb2.TestRequired(a=1, b=1, c=1),
+                     proto.optional_message)
+    self.assertEqual(1, proto.optional_message.a)
+    self.assertEqual(1, proto.optional_message.b)
+    self.assertEqual(1, proto.optional_message.c)
+
+  def testInitRepeatedKwargs(self):
+    proto = unittest_pb2.TestAllTypes(repeated_int32=[1, 2, 3])
+    self.assertTrue(proto.IsInitialized())
+    self.assertEqual(1, proto.repeated_int32[0])
+    self.assertEqual(2, proto.repeated_int32[1])
+    self.assertEqual(3, proto.repeated_int32[2])
+
+
 class OptionsTest(unittest.TestCase):
 
   def testMessageOptions(self):
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index 2d50bc4..1a0da55 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -38,6 +38,7 @@
 
 import os.path
 
+import unittest
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
 
@@ -351,6 +352,200 @@
   if expected != serialized:
     raise ValueError('Expected %r, found %r' % (expected, serialized))
 
+
+class GoldenMessageTestCase(unittest.TestCase):
+  """This adds methods to TestCase useful for verifying our Golden Message."""
+
+  def ExpectAllFieldsSet(self, message):
+    """Check all fields for correct values have after Set*Fields() is called."""
+    self.assertTrue(message.HasField('optional_int32'))
+    self.assertTrue(message.HasField('optional_int64'))
+    self.assertTrue(message.HasField('optional_uint32'))
+    self.assertTrue(message.HasField('optional_uint64'))
+    self.assertTrue(message.HasField('optional_sint32'))
+    self.assertTrue(message.HasField('optional_sint64'))
+    self.assertTrue(message.HasField('optional_fixed32'))
+    self.assertTrue(message.HasField('optional_fixed64'))
+    self.assertTrue(message.HasField('optional_sfixed32'))
+    self.assertTrue(message.HasField('optional_sfixed64'))
+    self.assertTrue(message.HasField('optional_float'))
+    self.assertTrue(message.HasField('optional_double'))
+    self.assertTrue(message.HasField('optional_bool'))
+    self.assertTrue(message.HasField('optional_string'))
+    self.assertTrue(message.HasField('optional_bytes'))
+
+    self.assertTrue(message.HasField('optionalgroup'))
+    self.assertTrue(message.HasField('optional_nested_message'))
+    self.assertTrue(message.HasField('optional_foreign_message'))
+    self.assertTrue(message.HasField('optional_import_message'))
+
+    self.assertTrue(message.optionalgroup.HasField('a'))
+    self.assertTrue(message.optional_nested_message.HasField('bb'))
+    self.assertTrue(message.optional_foreign_message.HasField('c'))
+    self.assertTrue(message.optional_import_message.HasField('d'))
+
+    self.assertTrue(message.HasField('optional_nested_enum'))
+    self.assertTrue(message.HasField('optional_foreign_enum'))
+    self.assertTrue(message.HasField('optional_import_enum'))
+
+    self.assertTrue(message.HasField('optional_string_piece'))
+    self.assertTrue(message.HasField('optional_cord'))
+
+    self.assertEqual(101, message.optional_int32)
+    self.assertEqual(102, message.optional_int64)
+    self.assertEqual(103, message.optional_uint32)
+    self.assertEqual(104, message.optional_uint64)
+    self.assertEqual(105, message.optional_sint32)
+    self.assertEqual(106, message.optional_sint64)
+    self.assertEqual(107, message.optional_fixed32)
+    self.assertEqual(108, message.optional_fixed64)
+    self.assertEqual(109, message.optional_sfixed32)
+    self.assertEqual(110, message.optional_sfixed64)
+    self.assertEqual(111, message.optional_float)
+    self.assertEqual(112, message.optional_double)
+    self.assertEqual(True, message.optional_bool)
+    self.assertEqual('115', message.optional_string)
+    self.assertEqual('116', message.optional_bytes)
+
+    self.assertEqual(117, message.optionalgroup.a);
+    self.assertEqual(118, message.optional_nested_message.bb)
+    self.assertEqual(119, message.optional_foreign_message.c)
+    self.assertEqual(120, message.optional_import_message.d)
+
+    self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+                     message.optional_nested_enum)
+    self.assertEqual(unittest_pb2.FOREIGN_BAZ, message.optional_foreign_enum)
+    self.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+                     message.optional_import_enum)
+
+    # -----------------------------------------------------------------
+
+    self.assertEqual(2, len(message.repeated_int32))
+    self.assertEqual(2, len(message.repeated_int64))
+    self.assertEqual(2, len(message.repeated_uint32))
+    self.assertEqual(2, len(message.repeated_uint64))
+    self.assertEqual(2, len(message.repeated_sint32))
+    self.assertEqual(2, len(message.repeated_sint64))
+    self.assertEqual(2, len(message.repeated_fixed32))
+    self.assertEqual(2, len(message.repeated_fixed64))
+    self.assertEqual(2, len(message.repeated_sfixed32))
+    self.assertEqual(2, len(message.repeated_sfixed64))
+    self.assertEqual(2, len(message.repeated_float))
+    self.assertEqual(2, len(message.repeated_double))
+    self.assertEqual(2, len(message.repeated_bool))
+    self.assertEqual(2, len(message.repeated_string))
+    self.assertEqual(2, len(message.repeated_bytes))
+
+    self.assertEqual(2, len(message.repeatedgroup))
+    self.assertEqual(2, len(message.repeated_nested_message))
+    self.assertEqual(2, len(message.repeated_foreign_message))
+    self.assertEqual(2, len(message.repeated_import_message))
+    self.assertEqual(2, len(message.repeated_nested_enum))
+    self.assertEqual(2, len(message.repeated_foreign_enum))
+    self.assertEqual(2, len(message.repeated_import_enum))
+
+    self.assertEqual(2, len(message.repeated_string_piece))
+    self.assertEqual(2, len(message.repeated_cord))
+
+    self.assertEqual(201, message.repeated_int32[0])
+    self.assertEqual(202, message.repeated_int64[0])
+    self.assertEqual(203, message.repeated_uint32[0])
+    self.assertEqual(204, message.repeated_uint64[0])
+    self.assertEqual(205, message.repeated_sint32[0])
+    self.assertEqual(206, message.repeated_sint64[0])
+    self.assertEqual(207, message.repeated_fixed32[0])
+    self.assertEqual(208, message.repeated_fixed64[0])
+    self.assertEqual(209, message.repeated_sfixed32[0])
+    self.assertEqual(210, message.repeated_sfixed64[0])
+    self.assertEqual(211, message.repeated_float[0])
+    self.assertEqual(212, message.repeated_double[0])
+    self.assertEqual(True, message.repeated_bool[0])
+    self.assertEqual('215', message.repeated_string[0])
+    self.assertEqual('216', message.repeated_bytes[0])
+
+    self.assertEqual(217, message.repeatedgroup[0].a)
+    self.assertEqual(218, message.repeated_nested_message[0].bb)
+    self.assertEqual(219, message.repeated_foreign_message[0].c)
+    self.assertEqual(220, message.repeated_import_message[0].d)
+
+    self.assertEqual(unittest_pb2.TestAllTypes.BAR,
+                     message.repeated_nested_enum[0])
+    self.assertEqual(unittest_pb2.FOREIGN_BAR,
+                     message.repeated_foreign_enum[0])
+    self.assertEqual(unittest_import_pb2.IMPORT_BAR,
+                     message.repeated_import_enum[0])
+
+    self.assertEqual(301, message.repeated_int32[1])
+    self.assertEqual(302, message.repeated_int64[1])
+    self.assertEqual(303, message.repeated_uint32[1])
+    self.assertEqual(304, message.repeated_uint64[1])
+    self.assertEqual(305, message.repeated_sint32[1])
+    self.assertEqual(306, message.repeated_sint64[1])
+    self.assertEqual(307, message.repeated_fixed32[1])
+    self.assertEqual(308, message.repeated_fixed64[1])
+    self.assertEqual(309, message.repeated_sfixed32[1])
+    self.assertEqual(310, message.repeated_sfixed64[1])
+    self.assertEqual(311, message.repeated_float[1])
+    self.assertEqual(312, message.repeated_double[1])
+    self.assertEqual(False, message.repeated_bool[1])
+    self.assertEqual('315', message.repeated_string[1])
+    self.assertEqual('316', message.repeated_bytes[1])
+
+    self.assertEqual(317, message.repeatedgroup[1].a)
+    self.assertEqual(318, message.repeated_nested_message[1].bb)
+    self.assertEqual(319, message.repeated_foreign_message[1].c)
+    self.assertEqual(320, message.repeated_import_message[1].d)
+
+    self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+                     message.repeated_nested_enum[1])
+    self.assertEqual(unittest_pb2.FOREIGN_BAZ,
+                     message.repeated_foreign_enum[1])
+    self.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+                     message.repeated_import_enum[1])
+
+    # -----------------------------------------------------------------
+
+    self.assertTrue(message.HasField('default_int32'))
+    self.assertTrue(message.HasField('default_int64'))
+    self.assertTrue(message.HasField('default_uint32'))
+    self.assertTrue(message.HasField('default_uint64'))
+    self.assertTrue(message.HasField('default_sint32'))
+    self.assertTrue(message.HasField('default_sint64'))
+    self.assertTrue(message.HasField('default_fixed32'))
+    self.assertTrue(message.HasField('default_fixed64'))
+    self.assertTrue(message.HasField('default_sfixed32'))
+    self.assertTrue(message.HasField('default_sfixed64'))
+    self.assertTrue(message.HasField('default_float'))
+    self.assertTrue(message.HasField('default_double'))
+    self.assertTrue(message.HasField('default_bool'))
+    self.assertTrue(message.HasField('default_string'))
+    self.assertTrue(message.HasField('default_bytes'))
+
+    self.assertTrue(message.HasField('default_nested_enum'))
+    self.assertTrue(message.HasField('default_foreign_enum'))
+    self.assertTrue(message.HasField('default_import_enum'))
+
+    self.assertEqual(401, message.default_int32)
+    self.assertEqual(402, message.default_int64)
+    self.assertEqual(403, message.default_uint32)
+    self.assertEqual(404, message.default_uint64)
+    self.assertEqual(405, message.default_sint32)
+    self.assertEqual(406, message.default_sint64)
+    self.assertEqual(407, message.default_fixed32)
+    self.assertEqual(408, message.default_fixed64)
+    self.assertEqual(409, message.default_sfixed32)
+    self.assertEqual(410, message.default_sfixed64)
+    self.assertEqual(411, message.default_float)
+    self.assertEqual(412, message.default_double)
+    self.assertEqual(False, message.default_bool)
+    self.assertEqual('415', message.default_string)
+    self.assertEqual('416', message.default_bytes)
+
+    self.assertEqual(unittest_pb2.TestAllTypes.FOO, message.default_nested_enum)
+    self.assertEqual(unittest_pb2.FOREIGN_FOO, message.default_foreign_enum)
+    self.assertEqual(unittest_import_pb2.IMPORT_FOO,
+                     message.default_import_enum)
+
 def GoldenFile(filename):
   """Finds the given golden file and returns a file object representing it."""
 
@@ -359,7 +554,8 @@
   while os.path.exists(path):
     if os.path.exists(os.path.join(path, 'src/google/protobuf')):
       # Found it.  Load the golden file from the testdata directory.
-      return file(os.path.join(path, 'src/google/protobuf/testdata', filename))
+      full_path = os.path.join(path, 'src/google/protobuf/testdata', filename)
+      return open(full_path, 'rb')
     path = os.path.join(path, '..')
 
   raise RuntimeError(
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 871590e..0cf2718 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -42,11 +42,16 @@
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_mset_pb2
 
-class TextFormatTest(unittest.TestCase):
-  def CompareToGoldenFile(self, text, golden_filename):
+
+class TextFormatTest(test_util.GoldenMessageTestCase):
+  def ReadGolden(self, golden_filename):
     f = test_util.GoldenFile(golden_filename)
     golden_lines = f.readlines()
     f.close()
+    return golden_lines
+
+  def CompareToGoldenFile(self, text, golden_filename):
+    golden_lines = self.ReadGolden(golden_filename)
     self.CompareToGoldenLines(text, golden_lines)
 
   def CompareToGoldenText(self, text, golden_text):
@@ -117,6 +122,276 @@
     return text.replace('e+0','e+').replace('e+0','e+') \
                .replace('e-0','e-').replace('e-0','e-')
 
+  def testMergeGolden(self):
+    golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
+    parsed_message = unittest_pb2.TestAllTypes()
+    text_format.Merge(golden_text, parsed_message)
+
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.assertEquals(message, parsed_message)
+
+  def testMergeGoldenExtensions(self):
+    golden_text = '\n'.join(self.ReadGolden(
+        'text_format_unittest_extensions_data.txt'))
+    parsed_message = unittest_pb2.TestAllExtensions()
+    text_format.Merge(golden_text, parsed_message)
+
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.assertEquals(message, parsed_message)
+
+  def testMergeAllFields(self):
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    ascii_text = text_format.MessageToString(message)
+
+    parsed_message = unittest_pb2.TestAllTypes()
+    text_format.Merge(ascii_text, parsed_message)
+    self.assertEqual(message, parsed_message)
+    self.ExpectAllFieldsSet(message)
+
+  def testMergeAllExtensions(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    ascii_text = text_format.MessageToString(message)
+
+    parsed_message = unittest_pb2.TestAllExtensions()
+    text_format.Merge(ascii_text, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def testMergeMessageSet(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('repeated_uint64: 1\n'
+            'repeated_uint64: 2\n')
+    text_format.Merge(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.Merge(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 testMergeExotic(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('repeated_int64: -9223372036854775808\n'
+            'repeated_uint64: 18446744073709551615\n'
+            'repeated_double: 123.456\n'
+            'repeated_double: 1.23e+22\n'
+            'repeated_double: 1.23e-18\n'
+            'repeated_string: \n'
+            '\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n')
+    text_format.Merge(text, message)
+
+    self.assertEqual(-9223372036854775808, message.repeated_int64[0])
+    self.assertEqual(18446744073709551615, message.repeated_uint64[0])
+    self.assertEqual(123.456, message.repeated_double[0])
+    self.assertEqual(1.23e22, message.repeated_double[1])
+    self.assertEqual(1.23e-18, message.repeated_double[2])
+    self.assertEqual(
+        '\000\001\a\b\f\n\r\t\v\\\'\"', message.repeated_string[0])
+
+  def testMergeUnknownField(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'unknown_field: 8\n'
+    self.assertRaisesWithMessage(
+        text_format.ParseError,
+        ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
+         '"unknown_field".'),
+        text_format.Merge, text, message)
+
+  def testMergeBadExtension(self):
+    message = unittest_pb2.TestAllTypes()
+    text = '[unknown_extension]: 8\n'
+    self.assertRaisesWithMessage(
+        text_format.ParseError,
+        '1:2 : Extension "unknown_extension" not registered.',
+        text_format.Merge, text, message)
+
+  def testMergeGroupNotClosed(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'RepeatedGroup: <'
+    self.assertRaisesWithMessage(
+        text_format.ParseError, '1:16 : Expected ">".',
+        text_format.Merge, text, message)
+
+    text = 'RepeatedGroup: {'
+    self.assertRaisesWithMessage(
+        text_format.ParseError, '1:16 : Expected "}".',
+        text_format.Merge, text, message)
+
+  def testMergeBadEnumValue(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'optional_nested_enum: BARR'
+    self.assertRaisesWithMessage(
+        text_format.ParseError,
+        ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
+         'has no value named BARR.'),
+        text_format.Merge, text, message)
+
+    message = unittest_pb2.TestAllTypes()
+    text = 'optional_nested_enum: 100'
+    self.assertRaisesWithMessage(
+        text_format.ParseError,
+        ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
+         'has no value with number 100.'),
+        text_format.Merge, text, message)
+
+  def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs):
+    """Same as assertRaises, but also compares the exception message."""
+    if hasattr(e_class, '__name__'):
+      exc_name = e_class.__name__
+    else:
+      exc_name = str(e_class)
+
+    try:
+      func(*args, **kwargs)
+    except e_class, expr:
+      if str(expr) != e:
+        msg = '%s raised, but with wrong message: "%s" instead of "%s"'
+        raise self.failureException(msg % (exc_name,
+                                           str(expr).encode('string_escape'),
+                                           e.encode('string_escape')))
+      return
+    else:
+      raise self.failureException('%s not raised' % exc_name)
+
+
+class TokenizerTest(unittest.TestCase):
+
+  def testSimpleTokenCases(self):
+    text = ('identifier1:"string1"\n     \n\n'
+            'identifier2 : \n \n123  \n  identifier3 :\'string\'\n'
+            'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
+            'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
+            'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
+            'ID12: 2222222222222222222')
+    tokenizer = text_format._Tokenizer(text)
+    methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
+               ':',
+               (tokenizer.ConsumeString, 'string1'),
+               (tokenizer.ConsumeIdentifier, 'identifier2'),
+               ':',
+               (tokenizer.ConsumeInt32, 123),
+               (tokenizer.ConsumeIdentifier, 'identifier3'),
+               ':',
+               (tokenizer.ConsumeString, 'string'),
+               (tokenizer.ConsumeIdentifier, 'identifiER_4'),
+               ':',
+               (tokenizer.ConsumeFloat, 1.1e+2),
+               (tokenizer.ConsumeIdentifier, 'ID5'),
+               ':',
+               (tokenizer.ConsumeFloat, -0.23),
+               (tokenizer.ConsumeIdentifier, 'ID6'),
+               ':',
+               (tokenizer.ConsumeString, 'aaaa\'bbbb'),
+               (tokenizer.ConsumeIdentifier, 'ID7'),
+               ':',
+               (tokenizer.ConsumeString, 'aa\"bb'),
+               (tokenizer.ConsumeIdentifier, 'ID8'),
+               ':',
+               '{',
+               (tokenizer.ConsumeIdentifier, 'A'),
+               ':',
+               (tokenizer.ConsumeFloat, float('inf')),
+               (tokenizer.ConsumeIdentifier, 'B'),
+               ':',
+               (tokenizer.ConsumeFloat, float('-inf')),
+               (tokenizer.ConsumeIdentifier, 'C'),
+               ':',
+               (tokenizer.ConsumeBool, True),
+               (tokenizer.ConsumeIdentifier, 'D'),
+               ':',
+               (tokenizer.ConsumeBool, False),
+               '}',
+               (tokenizer.ConsumeIdentifier, 'ID9'),
+               ':',
+               (tokenizer.ConsumeUint32, 22),
+               (tokenizer.ConsumeIdentifier, 'ID10'),
+               ':',
+               (tokenizer.ConsumeInt64, -111111111111111111),
+               (tokenizer.ConsumeIdentifier, 'ID11'),
+               ':',
+               (tokenizer.ConsumeInt32, -22),
+               (tokenizer.ConsumeIdentifier, 'ID12'),
+               ':',
+               (tokenizer.ConsumeUint64, 2222222222222222222)]
+
+    i = 0
+    while not tokenizer.AtEnd():
+      m = methods[i]
+      if type(m) == str:
+        token = tokenizer.token
+        self.assertEqual(token, m)
+        tokenizer.NextToken()
+      else:
+        self.assertEqual(m[1], m[0]())
+      i += 1
+
+  def testConsumeIntegers(self):
+    # This test only tests the failures in the integer parsing methods as well
+    # as the '0' special cases.
+    int64_max = (1 << 63) - 1
+    uint32_max = (1 << 32) - 1
+    text = '-1 %d %d' % (uint32_max + 1, int64_max + 1)
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64)
+    self.assertEqual(-1, tokenizer.ConsumeInt32())
+
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt32)
+    self.assertEqual(uint32_max + 1, tokenizer.ConsumeInt64())
+
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt64)
+    self.assertEqual(int64_max + 1, tokenizer.ConsumeUint64())
+    self.assertTrue(tokenizer.AtEnd())
+
+    text = '-0 -0 0 0'
+    tokenizer = text_format._Tokenizer(text)
+    self.assertEqual(0, tokenizer.ConsumeUint32())
+    self.assertEqual(0, tokenizer.ConsumeUint64())
+    self.assertEqual(0, tokenizer.ConsumeUint32())
+    self.assertEqual(0, tokenizer.ConsumeUint64())
+    self.assertTrue(tokenizer.AtEnd())
+
+  def testConsumeByteString(self):
+    text = '"string1\''
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = 'string1"'
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = '\n"\\xt"'
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = '\n"\\"'
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = '\n"\\x"'
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+  def testConsumeBool(self):
+    text = 'not-a-bool'
+    tokenizer = text_format._Tokenizer(text)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
+
+
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index c009627..a3bc57f 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -122,8 +122,10 @@
       try:
         unicode(proposed_value, 'ascii')
       except UnicodeDecodeError:
-        raise ValueError('%.1024r isn\'t in 7-bit ASCII encoding.'
-                         % (proposed_value))
+        raise ValueError('%.1024r has type str, but isn\'t in 7-bit ASCII '
+                         'encoding. Non-ASCII strings must be converted to '
+                         'unicode objects before being added.' %
+                         (proposed_value))
 
 
 class Int32ValueChecker(IntValueChecker):
diff --git a/python/google/protobuf/internal/wire_format.py b/python/google/protobuf/internal/wire_format.py
index 950267f..da6464d 100755
--- a/python/google/protobuf/internal/wire_format.py
+++ b/python/google/protobuf/internal/wire_format.py
@@ -64,6 +64,8 @@
 # "struct" format strings that will encode/decode the specified formats.
 FORMAT_UINT32_LITTLE_ENDIAN = '<I'
 FORMAT_UINT64_LITTLE_ENDIAN = '<Q'
+FORMAT_FLOAT_LITTLE_ENDIAN = '<f'
+FORMAT_DOUBLE_LITTLE_ENDIAN = '<d'
 
 
 # We'll have to provide alternate implementations of AppendLittleEndian*() on
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index 4da024c..9a88bdc 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -36,7 +36,6 @@
 
 __author__ = 'robinson@google.com (Will Robinson)'
 
-from google.protobuf import text_format
 
 class Error(Exception): pass
 class DecodeError(Error): pass
@@ -76,7 +75,7 @@
     return not self == other_msg
 
   def __str__(self):
-    return text_format.MessageToString(self)
+    raise NotImplementedError
 
   def MergeFrom(self, other_msg):
     """Merges the contents of the specified message into current message.
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 5ab7a1b..d65d8b6 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -62,6 +62,7 @@
 from google.protobuf.internal import wire_format
 from google.protobuf import descriptor as descriptor_mod
 from google.protobuf import message as message_mod
+from google.protobuf import text_format
 
 _FieldDescriptor = descriptor_mod.FieldDescriptor
 
@@ -291,7 +292,7 @@
 def _AddInitMethod(message_descriptor, cls):
   """Adds an __init__ method to cls."""
   fields = message_descriptor.fields
-  def init(self):
+  def init(self, **kwargs):
     self._cached_byte_size = 0
     self._cached_byte_size_dirty = False
     self._listener = message_listener_mod.NullMessageListener()
@@ -306,12 +307,30 @@
       if field.label != _FieldDescriptor.LABEL_REPEATED:
         setattr(self, _HasFieldName(field.name), False)
     self.Extensions = _ExtensionDict(self, cls._known_extensions)
+    for field_name, field_value in kwargs.iteritems():
+      field = _GetFieldByName(message_descriptor, field_name)
+      _MergeFieldOrExtension(self, field, field_value)
 
   init.__module__ = None
   init.__doc__ = None
   cls.__init__ = init
 
 
+def _GetFieldByName(message_descriptor, field_name):
+  """Returns a field descriptor by field name.
+
+  Args:
+    message_descriptor: A Descriptor describing all fields in message.
+    field_name: The name of the field to retrieve.
+  Returns:
+    The field descriptor associated with the field name.
+  """
+  try:
+    return message_descriptor.fields_by_name[field_name]
+  except KeyError:
+    raise ValueError('Protocol message has no "%s" field.' % field_name)
+
+
 def _AddPropertiesForFields(descriptor, cls):
   """Adds properties for all fields in this protocol message type."""
   for field in descriptor.fields:
@@ -543,10 +562,7 @@
 def _AddClearFieldMethod(cls):
   """Helper for _AddMessageMethods()."""
   def ClearField(self, field_name):
-    try:
-      field = self.DESCRIPTOR.fields_by_name[field_name]
-    except KeyError:
-      raise ValueError('Protocol message has no "%s" field.' % field_name)
+    field = _GetFieldByName(self.DESCRIPTOR, field_name)
     proto_field_name = field.name
     python_field_name = _ValueFieldName(proto_field_name)
     has_field_name = _HasFieldName(proto_field_name)
@@ -629,6 +645,13 @@
   cls.__eq__ = __eq__
 
 
+def _AddStrMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def __str__(self):
+    return text_format.MessageToString(self)
+  cls.__str__ = __str__
+
+
 def _AddSetListenerMethod(cls):
   """Helper for _AddMessageMethods()."""
   def SetListener(self, listener):
@@ -1090,7 +1113,7 @@
       content_start = decoder.Position()
       while decoder.Position() - content_start < length:
         element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
-      return decoder.Position() - content_start
+      return decoder.Position() - initial_position
   else:
     # Repeated composite.
     composite = element_list.add()
@@ -1275,6 +1298,7 @@
   _AddClearMethod(cls)
   _AddHasExtensionMethod(cls)
   _AddEqualsMethod(message_descriptor, cls)
+  _AddStrMethod(message_descriptor, cls)
   _AddSetListenerMethod(cls)
   _AddByteSizeMethod(message_descriptor, cls)
   _AddSerializeToStringMethod(message_descriptor, cls)
@@ -1436,6 +1460,20 @@
             if extension.label != _FieldDescriptor.LABEL_REPEATED)
     self._has_bits = dict.fromkeys(keys, False)
 
+    self._extensions_by_number = dict(
+        (f.number, f) for f in self._known_extensions.itervalues())
+
+    self._extensions_by_name = {}
+    for extension in self._known_extensions.itervalues():
+      if (extension.containing_type.GetOptions().message_set_wire_format and
+          extension.type == descriptor_mod.FieldDescriptor.TYPE_MESSAGE and
+          extension.message_type == extension.extension_scope and
+          extension.label == descriptor_mod.FieldDescriptor.LABEL_OPTIONAL):
+        extension_name = extension.message_type.full_name
+      else:
+        extension_name = extension.full_name
+      self._extensions_by_name[extension_name] = extension
+
   def __getitem__(self, extension_handle):
     """Returns the current value of the given extension handle."""
     # We don't care as much about keeping critical sections short in the
@@ -1609,7 +1647,15 @@
     Returns: A dict mapping field_number to (handle, field_descriptor),
       for *all* registered extensions for this dict.
     """
-    # TODO(robinson): Precompute and store this away.  Note that we'll have to
-    # be careful when we move away from having _known_extensions as a
-    # deep-copied member of this object.
-    return dict((f.number, f) for f in self._known_extensions.itervalues())
+    return self._extensions_by_number
+
+  def _FindExtensionByName(self, name):
+    """Tries to find a known extension with the specified name.
+
+    Args:
+      name: Extension full name.
+
+    Returns:
+      Extension field descriptor.
+    """
+    return self._extensions_by_name.get(name, None)
diff --git a/python/google/protobuf/service.py b/python/google/protobuf/service.py
index 9ec42fe..dd136c9 100755
--- a/python/google/protobuf/service.py
+++ b/python/google/protobuf/service.py
@@ -67,8 +67,6 @@
     and "done" will later be called with the response value.
 
     In the blocking case, RpcException will be raised on error.
-    Asynchronous calls must check status via the Failed method of the
-    RpcController.
 
     Preconditions:
     * method_descriptor.service == GetDescriptor
@@ -82,6 +80,9 @@
     Postconditions:
     * "done" will be called when the method is complete.  This may be
       before CallMethod() returns or it may be at some point in the future.
+    * If the RPC failed, the response value passed to "done" will be None.
+      Further details about the failure can be found by querying the
+      RpcController.
     """
     raise NotImplementedError
 
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 596ef94..1cddce6 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -33,10 +33,19 @@
 __author__ = 'kenton@google.com (Kenton Varda)'
 
 import cStringIO
+import re
 
+from collections import deque
+from google.protobuf.internal import type_checkers
 from google.protobuf import descriptor
 
-__all__ = [ 'MessageToString', 'PrintMessage', 'PrintField', 'PrintFieldValue' ]
+__all__ = [ 'MessageToString', 'PrintMessage', 'PrintField',
+            'PrintFieldValue', 'Merge' ]
+
+
+class ParseError(Exception):
+  """Thrown in case of ASCII parsing error."""
+
 
 def MessageToString(message):
   out = cStringIO.StringIO()
@@ -45,6 +54,7 @@
   out.close()
   return result
 
+
 def PrintMessage(message, out, indent = 0):
   for field, value in message.ListFields():
     if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
@@ -53,6 +63,7 @@
     else:
       PrintField(field, value, out, indent)
 
+
 def PrintField(field, value, out, indent = 0):
   """Print a single field name/value pair.  For repeated fields, the value
   should be a single element."""
@@ -82,6 +93,7 @@
   PrintFieldValue(field, value, out, indent)
   out.write('\n')
 
+
 def PrintFieldValue(field, value, out, indent = 0):
   """Print a single field value (not including name).  For repeated fields,
   the value should be a single element."""
@@ -104,6 +116,507 @@
   else:
     out.write(str(value))
 
+
+def Merge(text, message):
+  """Merges an ASCII representation of a protocol message into a message.
+
+  Args:
+    text: Message ASCII representation.
+    message: A protocol buffer message to merge into.
+
+  Raises:
+    ParseError: On ASCII parsing problems.
+  """
+  tokenizer = _Tokenizer(text)
+  while not tokenizer.AtEnd():
+    _MergeField(tokenizer, message)
+
+
+def _MergeField(tokenizer, message):
+  """Merges a single protocol message field into a message.
+
+  Args:
+    tokenizer: A tokenizer to parse the field name and values.
+    message: A protocol message to record the data.
+
+  Raises:
+    ParseError: In case of ASCII parsing problems.
+  """
+  message_descriptor = message.DESCRIPTOR
+  if tokenizer.TryConsume('['):
+    name = [tokenizer.ConsumeIdentifier()]
+    while tokenizer.TryConsume('.'):
+      name.append(tokenizer.ConsumeIdentifier())
+    name = '.'.join(name)
+
+    field = message.Extensions._FindExtensionByName(name)
+    if not field:
+      raise tokenizer.ParseErrorPreviousToken(
+          'Extension "%s" not registered.' % name)
+    elif message_descriptor != field.containing_type:
+      raise tokenizer.ParseErrorPreviousToken(
+          'Extension "%s" does not extend message type "%s".' % (
+              name, message_descriptor.full_name))
+    tokenizer.Consume(']')
+  else:
+    name = tokenizer.ConsumeIdentifier()
+    field = message_descriptor.fields_by_name.get(name, None)
+
+    # Group names are expected to be capitalized as they appear in the
+    # .proto file, which actually matches their type names, not their field
+    # names.
+    if not field:
+      field = message_descriptor.fields_by_name.get(name.lower(), None)
+      if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP:
+        field = None
+
+    if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and
+        field.message_type.name != name):
+      field = None
+
+    if not field:
+      raise tokenizer.ParseErrorPreviousToken(
+          'Message type "%s" has no field named "%s".' % (
+              message_descriptor.full_name, name))
+
+  if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+    tokenizer.TryConsume(':')
+
+    if tokenizer.TryConsume('<'):
+      end_token = '>'
+    else:
+      tokenizer.Consume('{')
+      end_token = '}'
+
+    if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+      if field.is_extension:
+        sub_message = message.Extensions[field].add()
+      else:
+        sub_message = getattr(message, field.name).add()
+    else:
+      if field.is_extension:
+        sub_message = message.Extensions[field]
+      else:
+        sub_message = getattr(message, field.name)
+
+    while not tokenizer.TryConsume(end_token):
+      if tokenizer.AtEnd():
+        raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token))
+      _MergeField(tokenizer, sub_message)
+  else:
+    _MergeScalarField(tokenizer, message, field)
+
+
+def _MergeScalarField(tokenizer, message, field):
+  """Merges a single protocol message scalar field into a message.
+
+  Args:
+    tokenizer: A tokenizer to parse the field value.
+    message: A protocol message to record the data.
+    field: The descriptor of the field to be merged.
+
+  Raises:
+    ParseError: In case of ASCII parsing problems.
+    RuntimeError: On runtime errors.
+  """
+  tokenizer.Consume(':')
+  value = None
+
+  if field.type in (descriptor.FieldDescriptor.TYPE_INT32,
+                    descriptor.FieldDescriptor.TYPE_SINT32,
+                    descriptor.FieldDescriptor.TYPE_SFIXED32):
+    value = tokenizer.ConsumeInt32()
+  elif field.type in (descriptor.FieldDescriptor.TYPE_INT64,
+                      descriptor.FieldDescriptor.TYPE_SINT64,
+                      descriptor.FieldDescriptor.TYPE_SFIXED64):
+    value = tokenizer.ConsumeInt64()
+  elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32,
+                      descriptor.FieldDescriptor.TYPE_FIXED32):
+    value = tokenizer.ConsumeUint32()
+  elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64,
+                      descriptor.FieldDescriptor.TYPE_FIXED64):
+    value = tokenizer.ConsumeUint64()
+  elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT,
+                      descriptor.FieldDescriptor.TYPE_DOUBLE):
+    value = tokenizer.ConsumeFloat()
+  elif field.type == descriptor.FieldDescriptor.TYPE_BOOL:
+    value = tokenizer.ConsumeBool()
+  elif field.type == descriptor.FieldDescriptor.TYPE_STRING:
+    value = tokenizer.ConsumeString()
+  elif field.type == descriptor.FieldDescriptor.TYPE_BYTES:
+    value = tokenizer.ConsumeByteString()
+  elif field.type == descriptor.FieldDescriptor.TYPE_ENUM:
+    # Enum can be specified by a number (the enum value), or by
+    # a string literal (the enum name).
+    enum_descriptor = field.enum_type
+    if tokenizer.LookingAtInteger():
+      number = tokenizer.ConsumeInt32()
+      enum_value = enum_descriptor.values_by_number.get(number, None)
+      if enum_value is None:
+        raise tokenizer.ParseErrorPreviousToken(
+            'Enum type "%s" has no value with number %d.' % (
+                enum_descriptor.full_name, number))
+    else:
+      identifier = tokenizer.ConsumeIdentifier()
+      enum_value = enum_descriptor.values_by_name.get(identifier, None)
+      if enum_value is None:
+        raise tokenizer.ParseErrorPreviousToken(
+            'Enum type "%s" has no value named %s.' % (
+                enum_descriptor.full_name, identifier))
+    value = enum_value.number
+  else:
+    raise RuntimeError('Unknown field type %d' % field.type)
+
+  if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+    if field.is_extension:
+      message.Extensions[field].append(value)
+    else:
+      getattr(message, field.name).append(value)
+  else:
+    if field.is_extension:
+      message.Extensions[field] = value
+    else:
+      setattr(message, field.name, value)
+
+
+class _Tokenizer(object):
+  """Protocol buffer ASCII representation tokenizer.
+
+  This class handles the lower level string parsing by splitting it into
+  meaningful tokens.
+
+  It was directly ported from the Java protocol buffer API.
+  """
+
+  _WHITESPACE = re.compile('(\\s|(#.*$))+', re.MULTILINE)
+  _TOKEN = re.compile(
+      '[a-zA-Z_][0-9a-zA-Z_+-]*|'           # an identifier
+      '[0-9+-][0-9a-zA-Z_.+-]*|'            # a number
+      '\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|'  # a double-quoted string
+      '\'([^\"\n\\\\]|\\\\.)*(\'|\\\\?$)')  # a single-quoted string
+  _IDENTIFIER = re.compile('\w+')
+  _INTEGER_CHECKERS = [type_checkers.Uint32ValueChecker(),
+                       type_checkers.Int32ValueChecker(),
+                       type_checkers.Uint64ValueChecker(),
+                       type_checkers.Int64ValueChecker()]
+  _FLOAT_INFINITY = re.compile('-?inf(inity)?f?', re.IGNORECASE)
+  _FLOAT_NAN = re.compile("nanf?", re.IGNORECASE)
+
+  def __init__(self, text_message):
+    self._text_message = text_message
+
+    self._position = 0
+    self._line = -1
+    self._column = 0
+    self._token_start = None
+    self.token = ''
+    self._lines = deque(text_message.split('\n'))
+    self._current_line = ''
+    self._previous_line = 0
+    self._previous_column = 0
+    self._SkipWhitespace()
+    self.NextToken()
+
+  def AtEnd(self):
+    """Checks the end of the text was reached.
+
+    Returns:
+      True iff the end was reached.
+    """
+    return not self._lines and not self._current_line
+
+  def _PopLine(self):
+    while not self._current_line:
+      if not self._lines:
+        self._current_line = ''
+        return
+      self._line += 1
+      self._column = 0
+      self._current_line = self._lines.popleft()
+
+  def _SkipWhitespace(self):
+    while True:
+      self._PopLine()
+      match = re.match(self._WHITESPACE, self._current_line)
+      if not match:
+        break
+      length = len(match.group(0))
+      self._current_line = self._current_line[length:]
+      self._column += length
+
+  def TryConsume(self, token):
+    """Tries to consume a given piece of text.
+
+    Args:
+      token: Text to consume.
+
+    Returns:
+      True iff the text was consumed.
+    """
+    if self.token == token:
+      self.NextToken()
+      return True
+    return False
+
+  def Consume(self, token):
+    """Consumes a piece of text.
+
+    Args:
+      token: Text to consume.
+
+    Raises:
+      ParseError: If the text couldn't be consumed.
+    """
+    if not self.TryConsume(token):
+      raise self._ParseError('Expected "%s".' % token)
+
+  def LookingAtInteger(self):
+    """Checks if the current token is an integer.
+
+    Returns:
+      True iff the current token is an integer.
+    """
+    if not self.token:
+      return False
+    c = self.token[0]
+    return (c >= '0' and c <= '9') or c == '-' or c == '+'
+
+  def ConsumeIdentifier(self):
+    """Consumes protocol message field identifier.
+
+    Returns:
+      Identifier string.
+
+    Raises:
+      ParseError: If an identifier couldn't be consumed.
+    """
+    result = self.token
+    if not re.match(self._IDENTIFIER, result):
+      raise self._ParseError('Expected identifier.')
+    self.NextToken()
+    return result
+
+  def ConsumeInt32(self):
+    """Consumes a signed 32bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If a signed 32bit integer couldn't be consumed.
+    """
+    try:
+      result = self._ParseInteger(self.token, is_signed=True, is_long=False)
+    except ValueError, e:
+      raise self._IntegerParseError(e)
+    self.NextToken()
+    return result
+
+  def ConsumeUint32(self):
+    """Consumes an unsigned 32bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If an unsigned 32bit integer couldn't be consumed.
+    """
+    try:
+      result = self._ParseInteger(self.token, is_signed=False, is_long=False)
+    except ValueError, e:
+      raise self._IntegerParseError(e)
+    self.NextToken()
+    return result
+
+  def ConsumeInt64(self):
+    """Consumes a signed 64bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If a signed 64bit integer couldn't be consumed.
+    """
+    try:
+      result = self._ParseInteger(self.token, is_signed=True, is_long=True)
+    except ValueError, e:
+      raise self._IntegerParseError(e)
+    self.NextToken()
+    return result
+
+  def ConsumeUint64(self):
+    """Consumes an unsigned 64bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If an unsigned 64bit integer couldn't be consumed.
+    """
+    try:
+      result = self._ParseInteger(self.token, is_signed=False, is_long=True)
+    except ValueError, e:
+      raise self._IntegerParseError(e)
+    self.NextToken()
+    return result
+
+  def ConsumeFloat(self):
+    """Consumes an floating point number.
+
+    Returns:
+      The number parsed.
+
+    Raises:
+      ParseError: If a floating point number couldn't be consumed.
+    """
+    text = self.token
+    if re.match(self._FLOAT_INFINITY, text):
+      self.NextToken()
+      if text.startswith('-'):
+        return float('-inf')
+      return float('inf')
+
+    if re.match(self._FLOAT_NAN, text):
+      self.NextToken()
+      return float('nan')
+
+    try:
+      result = float(text)
+    except ValueError, e:
+      raise self._FloatParseError(e)
+    self.NextToken()
+    return result
+
+  def ConsumeBool(self):
+    """Consumes a boolean value.
+
+    Returns:
+      The bool parsed.
+
+    Raises:
+      ParseError: If a boolean value couldn't be consumed.
+    """
+    if self.token == 'true':
+      self.NextToken()
+      return True
+    elif self.token == 'false':
+      self.NextToken()
+      return False
+    else:
+      raise self._ParseError('Expected "true" or "false".')
+
+  def ConsumeString(self):
+    """Consumes a string value.
+
+    Returns:
+      The string parsed.
+
+    Raises:
+      ParseError: If a string value couldn't be consumed.
+    """
+    return unicode(self.ConsumeByteString(), 'utf-8')
+
+  def ConsumeByteString(self):
+    """Consumes a byte array value.
+
+    Returns:
+      The array parsed (as a string).
+
+    Raises:
+      ParseError: If a byte array value couldn't be consumed.
+    """
+    text = self.token
+    if len(text) < 1 or text[0] not in ('\'', '"'):
+      raise self._ParseError('Exptected string.')
+
+    if len(text) < 2 or text[-1] != text[0]:
+      raise self._ParseError('String missing ending quote.')
+
+    try:
+      result = _CUnescape(text[1:-1])
+    except ValueError, e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def _ParseInteger(self, text, is_signed=False, is_long=False):
+    """Parses an integer.
+
+    Args:
+      text: The text to parse.
+      is_signed: True if a signed integer must be parsed.
+      is_long: True if a long integer must be parsed.
+
+    Returns:
+      The integer value.
+
+    Raises:
+      ValueError: Thrown Iff the text is not a valid integer.
+    """
+    pos = 0
+    if text.startswith('-'):
+      pos += 1
+
+    base = 10
+    if text.startswith('0x', pos) or text.startswith('0X', pos):
+      base = 16
+    elif text.startswith('0', pos):
+      base = 8
+
+    # Do the actual parsing. Exception handling is propagated to caller.
+    result = int(text, base)
+
+    # Check if the integer is sane. Exceptions handled by callers.
+    checker = self._INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
+    checker.CheckValue(result)
+    return result
+
+  def ParseErrorPreviousToken(self, message):
+    """Creates and *returns* a ParseError for the previously read token.
+
+    Args:
+      message: A message to set for the exception.
+
+    Returns:
+      A ParseError instance.
+    """
+    return ParseError('%d:%d : %s' % (
+        self._previous_line + 1, self._previous_column + 1, message))
+
+  def _ParseError(self, message):
+    """Creates and *returns* a ParseError for the current token."""
+    return ParseError('%d:%d : %s' % (
+        self._line + 1, self._column + 1, message))
+
+  def _IntegerParseError(self, e):
+    return self._ParseError('Couldn\'t parse integer: ' + str(e))
+
+  def _FloatParseError(self, e):
+    return self._ParseError('Couldn\'t parse number: ' + str(e))
+
+  def NextToken(self):
+    """Reads the next meaningful token."""
+    self._previous_line = self._line
+    self._previous_column = self._column
+    if self.AtEnd():
+      self.token = ''
+      return
+    self._column += len(self.token)
+
+    # Make sure there is data to work on.
+    self._PopLine()
+
+    match = re.match(self._TOKEN, self._current_line)
+    if match:
+      token = match.group(0)
+      self._current_line = self._current_line[len(token):]
+      self.token = token
+    else:
+      self.token = self._current_line[0]
+      self._current_line = self._current_line[1:]
+    self._SkipWhitespace()
+
+
 # text.encode('string_escape') does not seem to satisfy our needs as it
 # encodes unprintable characters using two-digit hex escapes whereas our
 # C++ unescaping function allows hex escapes to be any length.  So,
@@ -123,3 +636,15 @@
     if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes
     return c
   return "".join([escape(c) for c in text])
+
+
+_CUNESCAPE_HEX = re.compile('\\\\x([0-9a-fA-F]{2}|[0-9a-f-A-F])')
+
+
+def _CUnescape(text):
+  def ReplaceHex(m):
+    return chr(int(m.group(0)[2:], 16))
+  # This is required because the 'string_escape' encoding doesn't
+  # allow single-digit hex escapes (like '\xf').
+  result = _CUNESCAPE_HEX.sub(ReplaceHex, text)
+  return result.decode('string_escape')
diff --git a/src/Makefile.am b/src/Makefile.am
index 3e32c25..e4a30ab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,21 +43,25 @@
   google/protobuf/descriptor_database.h                        \
   google/protobuf/dynamic_message.h                            \
   google/protobuf/extension_set.h                              \
+  google/protobuf/generated_message_util.h                     \
   google/protobuf/generated_message_reflection.h               \
   google/protobuf/message.h                                    \
+  google/protobuf/message_lite.h                               \
   google/protobuf/reflection_ops.h                             \
   google/protobuf/repeated_field.h                             \
   google/protobuf/service.h                                    \
   google/protobuf/text_format.h                                \
   google/protobuf/unknown_field_set.h                          \
   google/protobuf/wire_format.h                                \
-  google/protobuf/wire_format_inl.h                            \
+  google/protobuf/wire_format_lite.h                           \
+  google/protobuf/wire_format_lite_inl.h                       \
   google/protobuf/io/coded_stream.h                            \
   $(GZHEADERS)                                                 \
   google/protobuf/io/printer.h                                 \
   google/protobuf/io/tokenizer.h                               \
   google/protobuf/io/zero_copy_stream.h                        \
   google/protobuf/io/zero_copy_stream_impl.h                   \
+  google/protobuf/io/zero_copy_stream_impl_lite.h              \
   google/protobuf/compiler/code_generator.h                    \
   google/protobuf/compiler/command_line_interface.h            \
   google/protobuf/compiler/importer.h                          \
@@ -68,6 +72,8 @@
 
 lib_LTLIBRARIES = libprotobuf.la libprotoc.la
 
+# TODO(kenton):  Separate lite and full libraries.  Also make sure lite_unittest
+#   only links against the lite lib.
 libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
 libprotobuf_la_LDFLAGS = -version-info 3:0:0
 libprotobuf_la_SOURCES =                                       \
@@ -89,20 +95,25 @@
   google/protobuf/descriptor_database.cc                       \
   google/protobuf/dynamic_message.cc                           \
   google/protobuf/extension_set.cc                             \
+  google/protobuf/extension_set_heavy.cc                       \
+  google/protobuf/generated_message_util.cc                    \
   google/protobuf/generated_message_reflection.cc              \
   google/protobuf/message.cc                                   \
+  google/protobuf/message_lite.cc                              \
   google/protobuf/reflection_ops.cc                            \
   google/protobuf/repeated_field.cc                            \
   google/protobuf/service.cc                                   \
   google/protobuf/text_format.cc                               \
   google/protobuf/unknown_field_set.cc                         \
   google/protobuf/wire_format.cc                               \
+  google/protobuf/wire_format_lite.cc                          \
   google/protobuf/io/coded_stream.cc                           \
   google/protobuf/io/gzip_stream.cc                            \
   google/protobuf/io/printer.cc                                \
   google/protobuf/io/tokenizer.cc                              \
   google/protobuf/io/zero_copy_stream.cc                       \
   google/protobuf/io/zero_copy_stream_impl.cc                  \
+  google/protobuf/io/zero_copy_stream_impl_lite.cc             \
   google/protobuf/compiler/importer.cc                         \
   google/protobuf/compiler/parser.cc
 
@@ -171,6 +182,9 @@
   google/protobuf/unittest_optimize_for.proto                  \
   google/protobuf/unittest_embed_optimize_for.proto            \
   google/protobuf/unittest_custom_options.proto                \
+  google/protobuf/unittest_lite.proto                          \
+  google/protobuf/unittest_import_lite.proto                   \
+  google/protobuf/unittest_lite_imports_nonlite.proto          \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
 
 EXTRA_DIST =                                                   \
@@ -186,7 +200,14 @@
   google/protobuf/io/package_info.h                            \
   google/protobuf/compiler/package_info.h
 
+protoc_lite_outputs =                                          \
+  google/protobuf/unittest_lite.pb.cc                          \
+  google/protobuf/unittest_lite.pb.h                           \
+  google/protobuf/unittest_import_lite.pb.cc                   \
+  google/protobuf/unittest_import_lite.pb.h
+
 protoc_outputs =                                               \
+  $(protoc_lite_outputs)                                       \
   google/protobuf/unittest.pb.cc                               \
   google/protobuf/unittest.pb.h                                \
   google/protobuf/unittest_empty.pb.cc                         \
@@ -201,6 +222,8 @@
   google/protobuf/unittest_embed_optimize_for.pb.h             \
   google/protobuf/unittest_custom_options.pb.cc                \
   google/protobuf/unittest_custom_options.pb.h                 \
+  google/protobuf/unittest_lite_imports_nonlite.pb.cc          \
+  google/protobuf/unittest_lite_imports_nonlite.pb.h           \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc  \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
 
@@ -240,7 +263,7 @@
   google/protobuf/testing/file.cc                              \
   google/protobuf/testing/file.h
 
-check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test $(GZCHECKPROGRAMS)
+check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZCHECKPROGRAMS)
 protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
                       $(top_builddir)/gtest/lib/libgtest.la       \
                       $(top_builddir)/gtest/lib/libgtest_main.la
@@ -290,6 +313,14 @@
   $(COMMON_TEST_SOURCES)
 nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
 
+# Build lite_unittest separately, since it doesn't use gtest.
+protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la
+protobuf_lite_test_SOURCES =                                           \
+  google/protobuf/lite_unittest.cc                                     \
+  google/protobuf/test_util_lite.cc                                    \
+  google/protobuf/test_util_lite.h
+nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
+
 if HAVE_ZLIB
 zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
 zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
@@ -298,4 +329,4 @@
 zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
 endif
 
-TESTS = protobuf-test protobuf-lazy-descriptor-test $(GZTESTS)
+TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZTESTS)
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 149d34a..0def84d 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -34,6 +34,8 @@
 
 #include <google/protobuf/compiler/code_generator.h>
 
+#include <google/protobuf/stubs/strutil.h>
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -41,6 +43,26 @@
 CodeGenerator::~CodeGenerator() {}
 OutputDirectory::~OutputDirectory() {}
 
+// Parses a set of comma-delimited name/value pairs.
+void ParseGeneratorParameter(const string& text,
+			     vector<pair<string, string> >* output) {
+  vector<string> parts;
+  SplitStringUsing(text, ",", &parts);
+
+  for (int i = 0; i < parts.size(); i++) {
+    string::size_type equals_pos = parts[i].find_first_of('=');
+    pair<string, string> value;
+    if (equals_pos == string::npos) {
+      value.first = parts[i];
+      value.second = "";
+    } else {
+      value.first = parts[i].substr(0, equals_pos);
+      value.second = parts[i].substr(equals_pos + 1);
+    }
+    output->push_back(value);
+  }
+}
+
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index d22974e..8a7081f 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -40,6 +40,8 @@
 
 #include <google/protobuf/stubs/common.h>
 #include <string>
+#include <vector>
+#include <utility>
 
 namespace google {
 namespace protobuf {
@@ -105,6 +107,15 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
 };
 
+// Several code generators treat the parameter argument as holding a
+// list of options separated by commas.  This helper function parses
+// a set of comma-delimited name/value pairs: e.g.,
+//   "foo=bar,baz,qux=corge"
+// parses to the pairs:
+//   ("foo", "bar"), ("baz", ""), ("qux", "corge")
+extern void ParseGeneratorParameter(const string&,
+				    vector<pair<string, string> >*);
+
 }  // namespace compiler
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 875cbef..90e9172 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -95,24 +95,39 @@
   }
 
   printer->Print(vars,
-    "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"
     "$dllexport$bool $classname$_IsValid(int value);\n"
     "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
     "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
     "\n");
 
-  // The _Name and _Parse methods
-  printer->Print(vars,
-    "inline const ::std::string& $classname$_Name($classname$ value) {\n"
-    "  return ::google::protobuf::internal::NameOfEnum(\n"
-    "    $classname$_descriptor(), value);\n"
-    "}\n");
-  printer->Print(vars,
-    "inline bool $classname$_Parse(\n"
-    "    const ::std::string& name, $classname$* value) {\n"
-    "  return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
-    "    $classname$_descriptor(), name, value);\n"
-    "}\n");
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(vars,
+      "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
+    // The _Name and _Parse methods
+    printer->Print(vars,
+      "inline const ::std::string& $classname$_Name($classname$ value) {\n"
+      "  return ::google::protobuf::internal::NameOfEnum(\n"
+      "    $classname$_descriptor(), value);\n"
+      "}\n");
+    printer->Print(vars,
+      "inline bool $classname$_Parse(\n"
+      "    const ::std::string& name, $classname$* value) {\n"
+      "  return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
+      "    $classname$_descriptor(), name, value);\n"
+      "}\n");
+  }
+}
+
+void EnumGenerator::
+GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(
+      "template <>\n"
+      "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
+      "  return $classname$_descriptor();\n"
+      "}\n",
+      "classname", ClassName(descriptor_, true));
+  }
 }
 
 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
@@ -128,24 +143,28 @@
   }
 
   printer->Print(vars,
-    "static inline const ::google::protobuf::EnumDescriptor*\n"
-    "$nested_name$_descriptor() {\n"
-    "  return $classname$_descriptor();\n"
-    "}\n"
     "static inline bool $nested_name$_IsValid(int value) {\n"
     "  return $classname$_IsValid(value);\n"
     "}\n"
-    "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
-    "  return $classname$_Name(value);\n"
-    "}\n"
-    "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
-    "    $nested_name$* value) {\n"
-    "  return $classname$_Parse(name, value);\n"
-    "}\n"
     "static const $nested_name$ $nested_name$_MIN =\n"
     "  $classname$_$nested_name$_MIN;\n"
     "static const $nested_name$ $nested_name$_MAX =\n"
     "  $classname$_$nested_name$_MAX;\n");
+
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(vars,
+      "static inline const ::google::protobuf::EnumDescriptor*\n"
+      "$nested_name$_descriptor() {\n"
+      "  return $classname$_descriptor();\n"
+      "}\n"
+      "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
+      "  return $classname$_Name(value);\n"
+      "}\n"
+      "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
+      "    $nested_name$* value) {\n"
+      "  return $classname$_Parse(name, value);\n"
+      "}\n");
+  }
 }
 
 void EnumGenerator::GenerateDescriptorInitializer(
@@ -168,11 +187,15 @@
   map<string, string> vars;
   vars["classname"] = classname_;
 
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(vars,
+      "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
+      "  protobuf_AssignDescriptorsOnce();\n"
+      "  return $classname$_descriptor_;\n"
+      "}\n");
+  }
+
   printer->Print(vars,
-    "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_descriptor_;\n"
-    "}\n"
     "bool $classname$_IsValid(int value) {\n"
     "  switch(value) {\n");
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 9f2e5fe..58f7721 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -63,6 +63,10 @@
   // nested enums.
   void GenerateDefinition(io::Printer* printer);
 
+  // Generate specialization of GetEnumDescriptor<MyEnum>().
+  // Precondition: in ::google::protobuf namespace.
+  void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+
   // For enums nested within a message, generate code to import all the enum's
   // symbols (e.g. the enum type name, all its values, etc.) into the class's
   // namespace.  This should be placed inside the class definition in the
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index b90eb37..7ca11c8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -35,7 +35,7 @@
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -43,24 +43,14 @@
 namespace compiler {
 namespace cpp {
 
-using internal::WireFormat;
-
 namespace {
 
-// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
-//   repeat code between this and the other field types.
 void SetEnumVariables(const FieldDescriptor* descriptor,
                       map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, variables);
   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
-
-  (*variables)["name"] = FieldName(descriptor);
   (*variables)["type"] = ClassName(descriptor->enum_type(), true);
   (*variables)["default"] = SimpleItoa(default_value->number());
-  (*variables)["index"] = SimpleItoa(descriptor->index());
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
-  (*variables)["tag_size"] = SimpleItoa(
-    WireFormat::TagSize(descriptor->number(), descriptor->type()));
 }
 
 }  // namespace
@@ -83,8 +73,8 @@
 void EnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline $type$ $name$() const;\n"
-    "inline void set_$name$($type$ value);\n");
+    "inline $type$ $name$() const$deprecation$;\n"
+    "inline void set_$name$($type$ value)$deprecation$;\n");
 }
 
 void EnumFieldGenerator::
@@ -124,33 +114,37 @@
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
     "int value;\n"
-    "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
+    "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
     "if ($type$_IsValid(value)) {\n"
-    "  set_$name$(static_cast< $type$ >(value));\n"
-    "} else {\n"
-    "  mutable_unknown_fields()->AddVarint($number$, value);\n"
+    "  set_$name$(static_cast< $type$ >(value));\n");
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print(variables_,
+      "} else {\n"
+      "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+  }
+  printer->Print(variables_,
     "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "::google::protobuf::internal::WireFormat::WriteEnum("
-      "$number$, this->$name$(), output);\n");
+    "::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
+    "  $number$, this->$name$(), output);\n");
 }
 
 void EnumFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "target = ::google::protobuf::internal::WireFormat::WriteEnumToArray("
-      "$number$, this->$name$(), target);\n");
+    "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
+    "  $number$, this->$name$(), target);\n");
 }
 
 void EnumFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
-    "  ::google::protobuf::internal::WireFormat::EnumSize(this->$name$());\n");
+    "  ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
 }
 
 // ===================================================================
@@ -167,8 +161,7 @@
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
     "::google::protobuf::RepeatedField<int> $name$_;\n");
-  if (descriptor_->options().packed() &&
-      descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
     printer->Print(variables_,
       "mutable int _$name$_cached_byte_size_;\n");
   }
@@ -177,11 +170,11 @@
 void RepeatedEnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedField<int>& $name$() const;\n"
-    "inline ::google::protobuf::RepeatedField<int>* mutable_$name$();\n"
-    "inline $type$ $name$(int index) const;\n"
-    "inline void set_$name$(int index, $type$ value);\n"
-    "inline void add_$name$($type$ value);\n");
+    "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+    "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n"
+    "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");
 }
 
 void RepeatedEnumFieldGenerator::
@@ -238,7 +231,7 @@
           "input->PushLimit(length);\n"
       "while (input->BytesUntilLimit() > 0) {\n"
       "  int value;\n"
-      "  DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
+      "  DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
       "  if ($type$_IsValid(value)) {\n"
       "    add_$name$(static_cast< $type$ >(value));\n"
       "  }\n"
@@ -247,11 +240,15 @@
   } else {
     printer->Print(variables_,
       "int value;\n"
-      "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
       "if ($type$_IsValid(value)) {\n"
-      "  add_$name$(static_cast< $type$ >(value));\n"
-      "} else {\n"
-      "  mutable_unknown_fields()->AddVarint($number$, value);\n"
+      "  add_$name$(static_cast< $type$ >(value));\n");
+    if (HasUnknownFields(descriptor_->file())) {
+      printer->Print(variables_,
+        "} else {\n"
+        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+    }
+    printer->Print(variables_,
       "}\n");
   }
 }
@@ -262,10 +259,10 @@
     // Write the tag and the size.
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
-      "  ::google::protobuf::internal::WireFormat::WriteTag("
-          "$number$, "
-          "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
-          "output);\n"
+      "  ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
+      "    $number$,\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
+      "    output);\n"
       "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
       "}\n");
   }
@@ -273,12 +270,12 @@
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
-      "  ::google::protobuf::internal::WireFormat::WriteEnumNoTag("
-          "this->$name$(i), output);\n");
+      "  ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
+      "    this->$name$(i), output);\n");
   } else {
     printer->Print(variables_,
-      "  ::google::protobuf::internal::WireFormat::WriteEnum("
-          "$number$, this->$name$(i), output);\n");
+      "  ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
+      "    $number$, this->$name$(i), output);\n");
   }
   printer->Print("}\n");
 }
@@ -289,24 +286,24 @@
     // Write the tag and the size.
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
-      "  target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
-          "$number$, "
-          "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
-          "target);\n"
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
+      "    $number$,\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
+      "    target);\n"
       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
-          "_$name$_cached_byte_size_, target);\n"
+      "    _$name$_cached_byte_size_, target);\n"
       "}\n");
   }
   printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
-      "  target = ::google::protobuf::internal::WireFormat::WriteEnumNoTagToArray("
-          "this->$name$(i), target);\n");
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
+      "    this->$name$(i), target);\n");
   } else {
     printer->Print(variables_,
-      "  target = ::google::protobuf::internal::WireFormat::WriteEnumToArray("
-          "$number$, this->$name$(i), target);\n");
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
+      "    $number$, this->$name$(i), target);\n");
   }
   printer->Print("}\n");
 }
@@ -319,15 +316,15 @@
   printer->Indent();
   printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n"
-      "  data_size += ::google::protobuf::internal::WireFormat::EnumSize(\n"
+      "  data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
       "    this->$name$(i));\n"
       "}\n");
 
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
       "if (data_size > 0) {\n"
-      "  total_size += $tag_size$ + "
-        "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
+      "  total_size += $tag_size$ +\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
       "}\n"
       "_$name$_cached_byte_size_ = data_size;\n"
       "total_size += data_size;\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index cd4806b..7208ed3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -133,6 +133,7 @@
     vars["global_name"] = global_name;
     printer->Print(vars,
       "const ::std::string $global_name$_default($default$);\n");
+
     // Update the default to refer to the string global.
     vars["default"] = global_name + "_default";
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 47daac7..c546e96 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -33,18 +33,37 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
 
+using internal::WireFormat;
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables) {
+  (*variables)["name"] = FieldName(descriptor);
+  (*variables)["index"] = SimpleItoa(descriptor->index());
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
+  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
+
+  (*variables)["tag_size"] = SimpleItoa(
+    WireFormat::TagSize(descriptor->number(), descriptor->type()));
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? " DEPRECATED_PROTOBUF_FIELD" : "";
+}
+
 FieldGenerator::~FieldGenerator() {}
 
 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 7e7c7f8..00ec2c7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -35,6 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 
+#include <map>
+#include <string>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.h>
 
@@ -49,6 +52,13 @@
 namespace compiler {
 namespace cpp {
 
+// Helper function: set variables in the map that are the same for all
+// field code generators.
+// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
+// 'deprecation'].
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables);
+
 class FieldGenerator {
  public:
   FieldGenerator() {}
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index f056ed5..51859bb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -125,13 +125,18 @@
 
   // OK, it's now safe to #include other files.
   printer->Print(
-    "#include <google/protobuf/generated_message_reflection.h>\n"
+    "#include <google/protobuf/generated_message_util.h>\n"
     "#include <google/protobuf/repeated_field.h>\n"
     "#include <google/protobuf/extension_set.h>\n");
 
-  if (file_->service_count() > 0) {
+  if (HasDescriptorMethods(file_)) {
     printer->Print(
-      "#include <google/protobuf/service.h>\n");
+      "#include <google/protobuf/generated_message_reflection.h>\n");
+
+    if (file_->service_count() > 0) {
+      printer->Print(
+        "#include <google/protobuf/service.h>\n");
+    }
   }
 
   for (int i = 0; i < file_->dependency_count(); i++) {
@@ -193,19 +198,21 @@
   printer->Print(kThickSeparator);
   printer->Print("\n");
 
-  // Generate service definitions.
-  for (int i = 0; i < file_->service_count(); i++) {
-    if (i > 0) {
-      printer->Print("\n");
-      printer->Print(kThinSeparator);
-      printer->Print("\n");
+  if (HasDescriptorMethods(file_)) {
+    // Generate service definitions.
+    for (int i = 0; i < file_->service_count(); i++) {
+      if (i > 0) {
+        printer->Print("\n");
+        printer->Print(kThinSeparator);
+        printer->Print("\n");
+      }
+      service_generators_[i]->GenerateDeclarations(printer);
     }
-    service_generators_[i]->GenerateDeclarations(printer);
-  }
 
-  printer->Print("\n");
-  printer->Print(kThickSeparator);
-  printer->Print("\n");
+    printer->Print("\n");
+    printer->Print(kThickSeparator);
+    printer->Print("\n");
+  }
 
   // Declare extension identifiers.
   for (int i = 0; i < file_->extension_count(); i++) {
@@ -228,6 +235,30 @@
   // Close up namespace.
   GenerateNamespaceClosers(printer);
 
+  // Emit GetEnumDescriptor specializations into google::protobuf namespace:
+  if (HasDescriptorMethods(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>(); }
+    // which appears in GetEnumDescriptor() specializations.
+    printer->Print(
+        "\n"
+        "#ifndef SWIG\n"
+        "namespace google {\nnamespace protobuf {\n"
+        "\n");
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+    }
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+    }
+    printer->Print(
+        "\n"
+        "}  // namespace google\n}  // namespace protobuf\n"
+        "#endif  // SWIG\n"
+        "\n");
+  }
+
   printer->Print(
     "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
     "filename_identifier", filename_identifier);
@@ -237,40 +268,52 @@
   printer->Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "\n"
+    // The generated code calls accessors that might be deprecated. We don't
+    // want the compiler to warn in generated code.
+    "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
     "#include \"$basename$.pb.h\"\n"
+
     "#include <google/protobuf/stubs/once.h>\n"
-    "#include <google/protobuf/descriptor.h>\n"
     "#include <google/protobuf/io/coded_stream.h>\n"
-    "#include <google/protobuf/reflection_ops.h>\n"
-    "#include <google/protobuf/wire_format_inl.h>\n",
+    "#include <google/protobuf/wire_format_lite_inl.h>\n",
     "basename", StripProto(file_->name()));
 
+  if (HasDescriptorMethods(file_)) {
+    printer->Print(
+      "#include <google/protobuf/descriptor.h>\n"
+      "#include <google/protobuf/reflection_ops.h>\n"
+      "#include <google/protobuf/wire_format.h>\n");
+  }
+
   GenerateNamespaceOpeners(printer);
 
-  printer->Print(
-    "\n"
-    "namespace {\n"
-    "\n");
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateDescriptorDeclarations(printer);
-  }
-  for (int i = 0; i < file_->enum_type_count(); i++) {
+  if (HasDescriptorMethods(file_)) {
     printer->Print(
-      "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
-      "name", ClassName(file_->enum_type(i), false));
-  }
-  for (int i = 0; i < file_->service_count(); i++) {
+      "\n"
+      "namespace {\n"
+      "\n");
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateDescriptorDeclarations(printer);
+    }
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      printer->Print(
+        "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
+        "name", ClassName(file_->enum_type(i), false));
+    }
+    for (int i = 0; i < file_->service_count(); i++) {
+      printer->Print(
+        "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
+        "name", file_->service(i)->name());
+    }
+
     printer->Print(
-      "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
-      "name", file_->service(i)->name());
+      "\n"
+      "}  // namespace\n"
+      "\n");
   }
 
-  printer->Print(
-    "\n"
-    "}  // namespace\n"
-    "\n");
-
-  // Define our externally-visible BuildDescriptors() function.
+  // Define our externally-visible BuildDescriptors() function.  (For the lite
+  // library, all this does is initialize default instances.)
   GenerateBuildDescriptors(printer);
 
   // Generate enums.
@@ -286,12 +329,14 @@
     message_generators_[i]->GenerateClassMethods(printer);
   }
 
-  // Generate services.
-  for (int i = 0; i < file_->service_count(); i++) {
-    if (i == 0) printer->Print("\n");
-    printer->Print(kThickSeparator);
-    printer->Print("\n");
-    service_generators_[i]->GenerateImplementation(printer);
+  if (HasDescriptorMethods(file_)) {
+    // Generate services.
+    for (int i = 0; i < file_->service_count(); i++) {
+      if (i == 0) printer->Print("\n");
+      printer->Print(kThickSeparator);
+      printer->Print("\n");
+      service_generators_[i]->GenerateImplementation(printer);
+    }
   }
 
   // Define extensions.
@@ -317,79 +362,83 @@
   // anyone calls descriptor() or GetReflection() on one of the types defined
   // in the file.
 
-  printer->Print(
-    "\n"
-    "void $assigndescriptorsname$() {\n",
-    "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
-  printer->Indent();
+  // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
+  // and we only use AddDescriptors() to allocate default instances.
+  if (HasDescriptorMethods(file_)) {
+    printer->Print(
+      "\n"
+      "void $assigndescriptorsname$() {\n",
+      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+    printer->Indent();
 
-  // Make sure the file has found its way into the pool.  If a descriptor
-  // is requested *during* static init then AddDescriptors() may not have
-  // been called yet, so we call it manually.  Note that it's fine if
-  // AddDescriptors() is called multiple times.
-  printer->Print(
-    "$adddescriptorsname$();\n",
-    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+    // Make sure the file has found its way into the pool.  If a descriptor
+    // is requested *during* static init then AddDescriptors() may not have
+    // been called yet, so we call it manually.  Note that it's fine if
+    // AddDescriptors() is called multiple times.
+    printer->Print(
+      "$adddescriptorsname$();\n",
+      "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
 
-  // Get the file's descriptor from the pool.
-  printer->Print(
-    "const ::google::protobuf::FileDescriptor* file =\n"
-    "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
-    "    \"$filename$\");\n"
-    // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
-    // being unused when compiling an empty .proto file.
-    "GOOGLE_CHECK(file != NULL);\n",
-    "filename", file_->name());
+    // Get the file's descriptor from the pool.
+    printer->Print(
+      "const ::google::protobuf::FileDescriptor* file =\n"
+      "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
+      "    \"$filename$\");\n"
+      // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
+      // being unused when compiling an empty .proto file.
+      "GOOGLE_CHECK(file != NULL);\n",
+      "filename", file_->name());
 
-  // Go through all the stuff defined in this file and generated code to
-  // assign the global descriptor pointers based on the file descriptor.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    // Go through all the stuff defined in this file and generated code to
+    // assign the global descriptor pointers based on the file descriptor.
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    }
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    }
+    for (int i = 0; i < file_->service_count(); i++) {
+      service_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "}\n"
+      "\n");
+
+    // ---------------------------------------------------------------
+
+    // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
+    // AssignDescriptors().  All later times, waits for the first call to
+    // complete and then returns.
+    printer->Print(
+      "namespace {\n"
+      "\n"
+      "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
+      "inline void protobuf_AssignDescriptorsOnce() {\n"
+      "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
+      "                 &$assigndescriptorsname$);\n"
+      "}\n"
+      "\n",
+      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+
+    // protobuf_RegisterTypes():  Calls
+    // MessageFactory::InternalRegisterGeneratedType() for each message type.
+    printer->Print(
+      "void protobuf_RegisterTypes(const ::std::string&) {\n"
+      "  protobuf_AssignDescriptorsOnce();\n");
+    printer->Indent();
+
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateTypeRegistrations(printer);
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "}\n"
+      "\n"
+      "}  // namespace\n");
   }
-  for (int i = 0; i < file_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
-  }
-  for (int i = 0; i < file_->service_count(); i++) {
-    service_generators_[i]->GenerateDescriptorInitializer(printer, i);
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "}\n"
-    "\n");
-
-  // -----------------------------------------------------------------
-
-  // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
-  // AssignDescriptors().  All later times, waits for the first call to
-  // complete and then returns.
-  printer->Print(
-    "namespace {\n"
-    "\n"
-    "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
-    "inline void protobuf_AssignDescriptorsOnce() {\n"
-    "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
-    "                 &$assigndescriptorsname$);\n"
-    "}\n"
-    "\n",
-    "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
-
-  // protobuf_RegisterTypes():  Calls
-  // MessageFactory::InternalRegisterGeneratedType() for each message type.
-  printer->Print(
-    "void protobuf_RegisterTypes() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n");
-  printer->Indent();
-
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateTypeRegistrations(printer);
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "}\n"
-    "\n"
-    "}  // namespace\n");
 
   // -----------------------------------------------------------------
 
@@ -442,32 +491,34 @@
       "name", GlobalAddDescriptorsName(dependency->name()));
   }
 
-  // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
-  // and embed it as a string literal, which is parsed and built into real
-  // descriptors at initialization time.
-  FileDescriptorProto file_proto;
-  file_->CopyTo(&file_proto);
-  string file_data;
-  file_proto.SerializeToString(&file_data);
+  if (HasDescriptorMethods(file_)) {
+    // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
+    // and embed it as a string literal, which is parsed and built into real
+    // descriptors at initialization time.
+    FileDescriptorProto file_proto;
+    file_->CopyTo(&file_proto);
+    string file_data;
+    file_proto.SerializeToString(&file_data);
 
-  printer->Print(
-    "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
+    printer->Print(
+      "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
 
-  // Only write 40 bytes per line.
-  static const int kBytesPerLine = 40;
-  for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
-    printer->Print("\n  \"$data$\"",
-      "data", CEscape(file_data.substr(i, kBytesPerLine)));
+    // Only write 40 bytes per line.
+    static const int kBytesPerLine = 40;
+    for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+      printer->Print("\n  \"$data$\"",
+        "data", CEscape(file_data.substr(i, kBytesPerLine)));
+    }
+    printer->Print(
+      ", $size$);\n",
+      "size", SimpleItoa(file_data.size()));
+
+    // Call MessageFactory::InternalRegisterGeneratedFile().
+    printer->Print(
+      "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
+      "  \"$filename$\", &protobuf_RegisterTypes);\n",
+      "filename", file_->name());
   }
-  printer->Print(
-    ", $size$);\n",
-    "size", SimpleItoa(file_data.size()));
-
-  // Call MessageFactory::InternalRegisterGeneratedFile().
-  printer->Print(
-    "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
-    "  \"$filename$\", &protobuf_RegisterTypes);\n",
-    "filename", file_->name());
 
   // Allocate and initialize default instances.  This can't be done lazily
   // since default instances are returned by simple accessors and are used with
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index f351525..d67d350 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -42,39 +42,12 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
 
-namespace {
-
-// Parses a set of comma-delimited name/value pairs, e.g.:
-//   "foo=bar,baz,qux=corge"
-// parses to the pairs:
-//   ("foo", "bar"), ("baz", ""), ("qux", "corge")
-void ParseOptions(const string& text, vector<pair<string, string> >* output) {
-  vector<string> parts;
-  SplitStringUsing(text, ",", &parts);
-
-  for (int i = 0; i < parts.size(); i++) {
-    string::size_type equals_pos = parts[i].find_first_of('=');
-    pair<string, string> value;
-    if (equals_pos == string::npos) {
-      value.first = parts[i];
-      value.second = "";
-    } else {
-      value.first = parts[i].substr(0, equals_pos);
-      value.second = parts[i].substr(equals_pos + 1);
-    }
-    output->push_back(value);
-  }
-}
-
-}  // namespace
-
 CppGenerator::CppGenerator() {}
 CppGenerator::~CppGenerator() {}
 
@@ -83,7 +56,7 @@
                             OutputDirectory* output_directory,
                             string* error) const {
   vector<pair<string, string> > options;
-  ParseOptions(parameter, &options);
+  ParseGeneratorParameter(parameter, &options);
 
   // -----------------------------------------------------------------
   // parse generator options
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 595aeae..723a8b4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -152,7 +152,18 @@
 
 string FieldConstantName(const FieldDescriptor *field) {
   string field_name = UnderscoresToCamelCase(field->name(), true);
-  return "k" + field_name + "FieldNumber";
+  string result = "k" + field_name + "FieldNumber";
+
+  if (!field->is_extension() &&
+      field->containing_type()->FindFieldByCamelcaseName(
+        field->camelcase_name()) != field) {
+    // This field's camelcase name is not unique.  As a hack, add the field
+    // number to the constant name.  This makes the constant rather useless,
+    // but what can we do?
+    result += "_" + SimpleItoa(field->number());
+  }
+
+  return result;
 }
 
 string StripProto(const string& filename) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 55fd7e2..83e1250 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -37,6 +37,7 @@
 
 #include <string>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
 
 namespace google {
 namespace protobuf {
@@ -105,6 +106,34 @@
 // Return the name of the ShutdownFile() function for a given file.
 string GlobalShutdownFileName(const string& filename);
 
+// Do message classes in this file keep track of unknown fields?
+inline const bool HasUnknownFields(const FileDescriptor *file) {
+  return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+}
+
+// Does this file have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+inline const bool HasGeneratedMethods(const FileDescriptor *file) {
+  return file->options().optimize_for() != FileOptions::CODE_SIZE;
+}
+
+// Do message classes in this file have descriptor and refelction methods?
+inline const bool HasDescriptorMethods(const FileDescriptor *file) {
+  return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+}
+
+// Should string fields in this file verify that their contents are UTF-8?
+inline const bool HasUtf8Verification(const FileDescriptor* file) {
+  return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+}
+
+// Should we generate a separate, super-optimized code path for serializing to
+// flat arrays?  We don't do this in Lite mode because we'd rather reduce code
+// size.
+inline const bool HasFastArraySerialization(const FileDescriptor* file) {
+  return file->options().optimize_for() == FileOptions::SPEED;
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 9852ee9..ae243dd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -34,14 +34,17 @@
 
 #include <algorithm>
 #include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <vector>
 #include <google/protobuf/compiler/cpp/cpp_message.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <google/protobuf/compiler/cpp/cpp_enum.h>
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/descriptor.pb.h>
 
 namespace google {
@@ -50,6 +53,7 @@
 namespace cpp {
 
 using internal::WireFormat;
+using internal::WireFormatLite;
 
 namespace {
 
@@ -196,6 +200,16 @@
 }
 
 void MessageGenerator::
+GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+  }
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+  }
+}
+
+void MessageGenerator::
 GenerateFieldAccessorDeclarations(io::Printer* printer) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
@@ -203,17 +217,16 @@
     PrintFieldComment(printer, field);
 
     map<string, string> vars;
-    vars["name"] = FieldName(field);
+    SetCommonFieldVariables(field, &vars);
     vars["constant_name"] = FieldConstantName(field);
-    vars["number"] = SimpleItoa(field->number());
 
     if (field->is_repeated()) {
-      printer->Print(vars, "inline int $name$_size() const;\n");
+      printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
     } else {
-      printer->Print(vars, "inline bool has_$name$() const;\n");
+      printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
     }
 
-    printer->Print(vars, "inline void clear_$name$();\n");
+    printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
     printer->Print(vars, "static const int $constant_name$ = $number$;\n");
 
     // Generate type-specific accessor declarations.
@@ -241,9 +254,7 @@
     PrintFieldComment(printer, field);
 
     map<string, string> vars;
-    vars["name"] = FieldName(field);
-    vars["index"] = SimpleItoa(field->index());
-    vars["classname"] = classname_;
+    SetCommonFieldVariables(field, &vars);
 
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
@@ -297,9 +308,11 @@
   } else {
     vars["dllexport"] = dllexport_decl_ + " ";
   }
+  vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ?
+                       "Message" : "MessageLite";
 
   printer->Print(vars,
-    "class $dllexport$$classname$ : public ::google::protobuf::Message {\n"
+    "class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n"
     " public:\n");
   printer->Indent();
 
@@ -313,16 +326,28 @@
     "  CopyFrom(from);\n"
     "  return *this;\n"
     "}\n"
-    "\n"
-    "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
-    "  return _unknown_fields_;\n"
-    "}\n"
-    "\n"
-    "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
-    "  return &_unknown_fields_;\n"
-    "}\n"
-    "\n"
-    "static const ::google::protobuf::Descriptor* descriptor();\n"
+    "\n");
+
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print(
+      "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
+      "  return _unknown_fields_;\n"
+      "}\n"
+      "\n"
+      "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
+      "  return &_unknown_fields_;\n"
+      "}\n"
+      "\n");
+  }
+
+  // Only generate this member if it's not disabled.
+  if (HasDescriptorMethods(descriptor_->file()) &&
+      !descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print(vars,
+      "static const ::google::protobuf::Descriptor* descriptor();\n");
+  }
+
+  printer->Print(vars,
     "static const $classname$& default_instance();\n"
     "void Swap($classname$* other);\n"
     "\n"
@@ -330,28 +355,29 @@
     "\n"
     "$classname$* New() const;\n");
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_->file())) {
+    if (HasDescriptorMethods(descriptor_->file())) {
+      printer->Print(vars,
+        "void CopyFrom(const ::google::protobuf::Message& from);\n"
+        "void MergeFrom(const ::google::protobuf::Message& from);\n");
+    } else {
+      printer->Print(vars,
+        "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
+    }
+
     printer->Print(vars,
-      "void CopyFrom(const ::google::protobuf::Message& from);\n"
-      "void MergeFrom(const ::google::protobuf::Message& from);\n"
       "void CopyFrom(const $classname$& from);\n"
       "void MergeFrom(const $classname$& from);\n"
       "void Clear();\n"
-      "bool IsInitialized() const;\n");
-
-    if (!descriptor_->options().message_set_wire_format()) {
-      // For message_set_wire_format, we don't generate parsing or
-      // serialization code even if optimize_for = SPEED, since MessageSet
-      // encoding is somewhat more complicated than normal extension encoding
-      // and we'd like to avoid having to implement it in multiple places.
-      // WireFormat's implementation is probably good enough.
-      printer->Print(vars,
-        "\n"
-        "int ByteSize() const;\n"
-        "bool MergePartialFromCodedStream(\n"
-        "    ::google::protobuf::io::CodedInputStream* input);\n"
-        "void SerializeWithCachedSizes(\n"
-        "    ::google::protobuf::io::CodedOutputStream* output) const;\n"
+      "bool IsInitialized() const;\n"
+      "\n"
+      "int ByteSize() const;\n"
+      "bool MergePartialFromCodedStream(\n"
+      "    ::google::protobuf::io::CodedInputStream* input);\n"
+      "void SerializeWithCachedSizes(\n"
+      "    ::google::protobuf::io::CodedOutputStream* output) const;\n");
+    if (HasFastArraySerialization(descriptor_->file())) {
+      printer->Print(
         "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
     }
   }
@@ -363,10 +389,19 @@
     "void SharedDtor();\n"
     "void SetCachedSize(int size) const { _cached_size_ = size; }\n"
     "public:\n"
-    "\n"
-    "const ::google::protobuf::Descriptor* GetDescriptor() const;\n"
-    "const ::google::protobuf::Reflection* GetReflection() const;\n"
-    "\n"
+    "\n");
+
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(
+      "::google::protobuf::Metadata GetMetadata() const;\n"
+      "\n");
+  } else {
+    printer->Print(
+      "::std::string GetTypeName() const;\n"
+      "\n");
+  }
+
+  printer->Print(
     "// nested types ----------------------------------------------------\n"
     "\n");
 
@@ -411,9 +446,13 @@
       "::google::protobuf::internal::ExtensionSet _extensions_;\n");
   }
 
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print(
+      "::google::protobuf::UnknownFieldSet _unknown_fields_;\n");
+  }
+
   // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
   printer->Print(
-    "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
     "mutable int _cached_size_;\n"
     "\n");
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -431,7 +470,8 @@
       GlobalAddDescriptorsName(descriptor_->file()->name()));
   printer->Print(
     "friend void $assigndescriptorsname$();\n"
-    "friend void $shutdownfilename$();\n",
+    "friend void $shutdownfilename$();\n"
+    "\n",
     "assigndescriptorsname",
       GlobalAssignDescriptorsName(descriptor_->file()->name()),
     "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
@@ -605,10 +645,15 @@
 void MessageGenerator::
 GenerateShutdownCode(io::Printer* printer) {
   printer->Print(
-    "delete $classname$::default_instance_;\n"
-    "delete $classname$_reflection_;\n",
+    "delete $classname$::default_instance_;\n",
     "classname", classname_);
 
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(
+      "delete $classname$_reflection_;\n",
+      "classname", classname_);
+  }
+
   // Handle nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     nested_generators_[i]->GenerateShutdownCode(printer);
@@ -655,29 +700,24 @@
   GenerateStructors(printer);
   printer->Print("\n");
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_->file())) {
     GenerateClear(printer);
     printer->Print("\n");
 
-    if (!descriptor_->options().message_set_wire_format()) {
-      // For message_set_wire_format, we don't generate parsing or
-      // serialization code even if optimize_for = SPEED, since MessageSet
-      // encoding is somewhat more complicated than normal extension encoding
-      // and we'd like to avoid having to implement it in multiple places.
-      // WireFormat's implementation is probably good enough.
-      GenerateMergeFromCodedStream(printer);
-      printer->Print("\n");
+    GenerateMergeFromCodedStream(printer);
+    printer->Print("\n");
 
-      GenerateSerializeWithCachedSizes(printer);
-      printer->Print("\n");
+    GenerateSerializeWithCachedSizes(printer);
+    printer->Print("\n");
 
+    if (HasFastArraySerialization(descriptor_->file())) {
       GenerateSerializeWithCachedSizesToArray(printer);
       printer->Print("\n");
-
-      GenerateByteSize(printer);
-      printer->Print("\n");
     }
 
+    GenerateByteSize(printer);
+    printer->Print("\n");
+
     GenerateMergeFrom(printer);
     printer->Print("\n");
 
@@ -691,16 +731,26 @@
   GenerateSwap(printer);
   printer->Print("\n");
 
-  printer->Print(
-    "const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {\n"
-    "  return descriptor();\n"
-    "}\n"
-    "\n"
-    "const ::google::protobuf::Reflection* $classname$::GetReflection() const {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_reflection_;\n"
-    "}\n",
-    "classname", classname_);
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(
+      "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
+      "  protobuf_AssignDescriptorsOnce();\n"
+      "  ::google::protobuf::Metadata metadata;\n"
+      "  metadata.descriptor = $classname$_descriptor_;\n"
+      "  metadata.reflection = $classname$_reflection_;\n"
+      "  return metadata;\n"
+      "}\n"
+      "\n",
+      "classname", classname_);
+  } else {
+    printer->Print(
+      "::std::string $classname$::GetTypeName() const {\n"
+      "  return \"$type_name$\";\n"
+      "}\n"
+      "\n",
+      "classname", classname_,
+      "type_name", descriptor_->full_name());
+  }
 }
 
 void MessageGenerator::
@@ -724,18 +774,6 @@
 }
 
 void MessageGenerator::
-GenerateInitializerList(io::Printer* printer) {
-  printer->Indent();
-  printer->Indent();
-
-  printer->Print(
-    "::google::protobuf::Message()");
-
-  printer->Outdent();
-  printer->Outdent();
-}
-
-void MessageGenerator::
 GenerateSharedConstructorCode(io::Printer* printer) {
   printer->Print(
     "void $classname$::SharedCtor() {\n",
@@ -797,17 +835,14 @@
 GenerateStructors(io::Printer* printer) {
   // Generate the default constructor.
   printer->Print(
-      "$classname$::$classname$()\n"
-      "  : ",
-      "classname", classname_);
-  GenerateInitializerList(printer);
-  printer->Print(" {\n"
+    "$classname$::$classname$() {\n"
     "  SharedCtor();\n"
-    "}\n");
+    "}\n",
+    "classname", classname_);
 
   printer->Print(
     "\n"
-    "void $classname$::InitAsDefaultInstance() {",
+    "void $classname$::InitAsDefaultInstance() {\n",
     "classname", classname_);
 
   // The default instance needs all of its embedded message pointers
@@ -833,15 +868,12 @@
 
   // Generate the copy constructor.
   printer->Print(
-      "$classname$::$classname$(const $classname$& from)\n"
-      "  : ",
-      "classname", classname_);
-  GenerateInitializerList(printer);
-  printer->Print(" {\n"
+    "$classname$::$classname$(const $classname$& from) {\n"
     "  SharedCtor();\n"
     "  MergeFrom(from);\n"
     "}\n"
-    "\n");
+    "\n",
+    "classname", classname_);
 
   // Generate the shared constructor code.
   GenerateSharedConstructorCode(printer);
@@ -857,12 +889,21 @@
   // Generate the shared destructor code.
   GenerateSharedDestructorCode(printer);
 
+  // Only generate this member if it's not disabled.
+  if (HasDescriptorMethods(descriptor_->file()) &&
+      !descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print(
+      "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
+      "  protobuf_AssignDescriptorsOnce();\n"
+      "  return $classname$_descriptor_;\n"
+      "}\n"
+      "\n",
+      "classname", classname_,
+      "adddescriptorsname",
+      GlobalAddDescriptorsName(descriptor_->file()->name()));
+  }
+
   printer->Print(
-    "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_descriptor_;\n"
-    "}\n"
-    "\n"
     "const $classname$& $classname$::default_instance() {\n"
     "  if (default_instance_ == NULL) $adddescriptorsname$();"
     "  return *default_instance_;\n"
@@ -951,8 +992,12 @@
   }
 
   printer->Print(
-    "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"
-    "mutable_unknown_fields()->Clear();\n");
+    "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print(
+      "mutable_unknown_fields()->Clear();\n");
+  }
 
   printer->Outdent();
   printer->Print("}\n");
@@ -967,7 +1012,7 @@
   printer->Print("if (other != this) {\n");
   printer->Indent();
 
-  if ( descriptor_->file()->options().optimize_for() == FileOptions::SPEED ) {
+  if (HasGeneratedMethods(descriptor_->file())) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* field = descriptor_->field(i);
       field_generators_.get(field).GenerateSwappingCode(printer);
@@ -978,7 +1023,9 @@
                      "i", SimpleItoa(i));
     }
 
-    printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+    if (HasUnknownFields(descriptor_->file())) {
+      printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+    }
     printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
     if (descriptor_->extension_range_count() > 0) {
       printer->Print("_extensions_.Swap(&other->_extensions_);\n");
@@ -987,7 +1034,6 @@
     printer->Print("GetReflection()->Swap(this, other);");
   }
 
-
   printer->Outdent();
   printer->Print("}\n");
   printer->Outdent();
@@ -996,31 +1042,42 @@
 
 void MessageGenerator::
 GenerateMergeFrom(io::Printer* printer) {
-  // Generate the generalized MergeFrom (aka that which takes in the Message
-  // base class as a parameter).
-  printer->Print(
-    "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
-    "  GOOGLE_CHECK_NE(&from, this);\n",
-    "classname", classname_);
-  printer->Indent();
+  if (HasDescriptorMethods(descriptor_->file())) {
+    // Generate the generalized MergeFrom (aka that which takes in the Message
+    // base class as a parameter).
+    printer->Print(
+      "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
+      "  GOOGLE_CHECK_NE(&from, this);\n",
+      "classname", classname_);
+    printer->Indent();
 
-  // Cast the message to the proper type. If we find that the message is
-  // *not* of the proper type, we can still call Merge via the reflection
-  // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
-  // for each message.
-  printer->Print(
-    "const $classname$* source =\n"
-    "  ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
-    "    &from);\n"
-    "if (source == NULL) {\n"
-    "  ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
-    "} else {\n"
-    "  MergeFrom(*source);\n"
-    "}\n",
-    "classname", classname_);
+    // Cast the message to the proper type. If we find that the message is
+    // *not* of the proper type, we can still call Merge via the reflection
+    // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
+    // for each message.
+    printer->Print(
+      "const $classname$* source =\n"
+      "  ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
+      "    &from);\n"
+      "if (source == NULL) {\n"
+      "  ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
+      "} else {\n"
+      "  MergeFrom(*source);\n"
+      "}\n",
+      "classname", classname_);
 
-  printer->Outdent();
-  printer->Print("}\n\n");
+    printer->Outdent();
+    printer->Print("}\n\n");
+  } else {
+    // Generate CheckTypeAndMergeFrom().
+    printer->Print(
+      "void $classname$::CheckTypeAndMergeFrom(\n"
+      "    const ::google::protobuf::MessageLite& from) {\n"
+      "  MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n"
+      "}\n"
+      "\n",
+      "classname", classname_);
+  }
 
   // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
   printer->Print(
@@ -1082,8 +1139,10 @@
     printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
   }
 
-  printer->Print(
-    "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print(
+      "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
+  }
 
   printer->Outdent();
   printer->Print("}\n");
@@ -1091,20 +1150,22 @@
 
 void MessageGenerator::
 GenerateCopyFrom(io::Printer* printer) {
-  // Generate the generalized CopyFrom (aka that which takes in the Message
-  // base class as a parameter).
-  printer->Print(
-    "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
-    "classname", classname_);
-  printer->Indent();
+  if (HasDescriptorMethods(descriptor_->file())) {
+    // Generate the generalized CopyFrom (aka that which takes in the Message
+    // base class as a parameter).
+    printer->Print(
+      "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
+      "classname", classname_);
+    printer->Indent();
 
-  printer->Print(
-    "if (&from == this) return;\n"
-    "Clear();\n"
-    "MergeFrom(from);\n");
+    printer->Print(
+      "if (&from == this) return;\n"
+      "Clear();\n"
+      "MergeFrom(from);\n");
 
-  printer->Outdent();
-  printer->Print("}\n\n");
+    printer->Outdent();
+    printer->Print("}\n\n");
+  }
 
   // Generate the class-specific CopyFrom.
   printer->Print(
@@ -1123,6 +1184,18 @@
 
 void MessageGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "bool $classname$::MergePartialFromCodedStream(\n"
+      "    ::google::protobuf::io::CodedInputStream* input) {\n"
+      "  return _extensions_.ParseMessageSet(input, default_instance_,\n"
+      "                                      mutable_unknown_fields());\n"
+      "}\n",
+      "classname", classname_);
+    return;
+  }
+
   printer->Print(
     "bool $classname$::MergePartialFromCodedStream(\n"
     "    ::google::protobuf::io::CodedInputStream* input) {\n"
@@ -1144,7 +1217,7 @@
     // creates a jump table that is 8x larger and sparser, and meanwhile the
     // if()s are highly predictable.
     printer->Print(
-      "switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {\n");
+      "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n");
 
     printer->Indent();
 
@@ -1158,8 +1231,8 @@
 
       printer->Print(
         "case $number$: {\n"
-        "  if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=\n"
-        "      ::google::protobuf::internal::WireFormat::WIRETYPE_$wiretype$) {\n"
+        "  if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=\n"
+        "      ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n"
         "    goto handle_uninterpreted;\n"
         "  }\n",
         "number", SimpleItoa(field->number()),
@@ -1214,8 +1287,8 @@
 
   // Is this an end-group tag?  If so, this must be the end of the message.
   printer->Print(
-    "if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==\n"
-    "    ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {\n"
+    "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
+    "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
     "  return true;\n"
     "}\n");
 
@@ -1228,10 +1301,10 @@
         descriptor_->extension_range(i);
       if (i > 0) printer->Print(" ||\n    ");
 
-      uint32 start_tag = WireFormat::MakeTag(
-        range->start, static_cast<WireFormat::WireType>(0));
-      uint32 end_tag = WireFormat::MakeTag(
-        range->end, static_cast<WireFormat::WireType>(0));
+      uint32 start_tag = WireFormatLite::MakeTag(
+        range->start, static_cast<WireFormatLite::WireType>(0));
+      uint32 end_tag = WireFormatLite::MakeTag(
+        range->end, static_cast<WireFormatLite::WireType>(0));
 
       if (range->end > FieldDescriptor::kMaxNumber) {
         printer->Print(
@@ -1244,17 +1317,29 @@
           "end", SimpleItoa(end_tag));
       }
     }
-    printer->Print(") {\n"
-      "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
-      "                              mutable_unknown_fields()));\n"
+    printer->Print(") {\n");
+    if (HasUnknownFields(descriptor_->file())) {
+      printer->Print(
+        "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+        "                              mutable_unknown_fields()));\n");
+    } else {
+      printer->Print(
+        "  DO_(_extensions_.ParseField(tag, input, default_instance_));\n");
+    }
+    printer->Print(
       "  continue;\n"
       "}\n");
   }
 
   // We really don't recognize this tag.  Skip it.
-  printer->Print(
-    "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
-    "      input, tag, mutable_unknown_fields()));\n");
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print(
+      "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
+      "      input, tag, mutable_unknown_fields()));\n");
+  } else {
+    printer->Print(
+      "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
+  }
 
   if (descriptor_->field_count() > 0) {
     printer->Print("break;\n");
@@ -1319,21 +1404,41 @@
 
 void MessageGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "void $classname$::SerializeWithCachedSizes(\n"
+      "    ::google::protobuf::io::CodedOutputStream* output) const {\n"
+      "  _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
+      "classname", classname_);
+    if (HasUnknownFields(descriptor_->file())) {
+      printer->Print(
+        "  ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
+        "      unknown_fields(), output);\n");
+    }
+    printer->Print(
+      "}\n");
+    return;
+  }
+
   printer->Print(
     "void $classname$::SerializeWithCachedSizes(\n"
     "    ::google::protobuf::io::CodedOutputStream* output) const {\n",
     "classname", classname_);
   printer->Indent();
 
-  printer->Print(
-    "::google::protobuf::uint8* raw_buffer = "
-      "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n"
-    "if (raw_buffer != NULL) {\n"
-    "  $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n"
-    "  return;\n"
-    "}\n"
-    "\n",
-    "classname", classname_);
+  if (HasFastArraySerialization(descriptor_->file())) {
+    printer->Print(
+      "::google::protobuf::uint8* raw_buffer = "
+        "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n"
+      "if (raw_buffer != NULL) {\n"
+      "  $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n"
+      "  return;\n"
+      "}\n"
+      "\n",
+      "classname", classname_);
+  }
+
   GenerateSerializeWithCachedSizesBody(printer, false);
 
   printer->Outdent();
@@ -1343,6 +1448,26 @@
 
 void MessageGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
+      "    ::google::protobuf::uint8* target) const {\n"
+      "  target =\n"
+      "      _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
+      "classname", classname_);
+    if (HasUnknownFields(descriptor_->file())) {
+      printer->Print(
+        "  target = ::google::protobuf::internal::WireFormat::\n"
+        "             SerializeUnknownMessageSetItemsToArray(\n"
+        "               unknown_fields(), target);\n");
+    }
+    printer->Print(
+      "  return target;\n"
+      "}\n");
+    return;
+  }
+
   printer->Print(
     "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
     "    ::google::protobuf::uint8* target) const {\n",
@@ -1389,26 +1514,46 @@
     }
   }
 
-  printer->Print("if (!unknown_fields().empty()) {\n");
-  printer->Indent();
-  if (to_array) {
-    printer->Print(
-      "target = "
-          "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
-      "    unknown_fields(), target);\n");
-  } else {
-    printer->Print(
-      "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
-      "    unknown_fields(), output);\n");
-  }
-  printer->Outdent();
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print("if (!unknown_fields().empty()) {\n");
+    printer->Indent();
+    if (to_array) {
+      printer->Print(
+        "target = "
+            "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+        "    unknown_fields(), target);\n");
+    } else {
+      printer->Print(
+        "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+        "    unknown_fields(), output);\n");
+    }
+    printer->Outdent();
 
-  printer->Print(
-    "}\n");
+    printer->Print(
+      "}\n");
+  }
 }
 
 void MessageGenerator::
 GenerateByteSize(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "int $classname$::ByteSize() const {\n"
+      "  int total_size = _extensions_.MessageSetByteSize();\n",
+      "classname", classname_);
+    if (HasUnknownFields(descriptor_->file())) {
+      printer->Print(
+        "  total_size += ::google::protobuf::internal::WireFormat::\n"
+        "      ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
+    }
+    printer->Print(
+      "  _cached_size_ = total_size;\n"
+      "  return total_size;\n"
+      "}\n");
+    return;
+  }
+
   printer->Print(
     "int $classname$::ByteSize() const {\n",
     "classname", classname_);
@@ -1478,14 +1623,16 @@
       "\n");
   }
 
-  printer->Print("if (!unknown_fields().empty()) {\n");
-  printer->Indent();
-  printer->Print(
-    "total_size +=\n"
-    "  ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
-    "    unknown_fields());\n");
-  printer->Outdent();
-  printer->Print("}\n");
+  if (HasUnknownFields(descriptor_->file())) {
+    printer->Print("if (!unknown_fields().empty()) {\n");
+    printer->Indent();
+    printer->Print(
+      "total_size +=\n"
+      "  ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+      "    unknown_fields());\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
 
   // We update _cached_size_ even though this is a const method.  In theory,
   // this is not thread-compatible, because concurrent writes have undefined
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 105574a..f1c5714 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -69,6 +69,10 @@
   // definitions because those classes use the enums definitions).
   void GenerateEnumDefinitions(io::Printer* printer);
 
+  // Generate specializations of GetEnumDescriptor<MyEnum>().
+  // Precondition: in ::google::protobuf namespace.
+  void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+
   // Generate definitions for this class and all its nested types.
   void GenerateClassDefinition(io::Printer* printer);
 
@@ -125,11 +129,6 @@
   // Generate the shared destructor code.
   void GenerateSharedDestructorCode(io::Printer* printer);
 
-  // Generate the member initializer list for the constructors. The member
-  // initializer list is shared between the default constructor and the copy
-  // constructor.
-  void GenerateInitializerList(io::Printer* printer);
-
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateMergeFromCodedStream(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 2a7eb3f..059fba6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -35,7 +35,6 @@
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -43,22 +42,12 @@
 namespace compiler {
 namespace cpp {
 
-using internal::WireFormat;
-
 namespace {
 
-// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
-//   repeat code between this and the other field types.
 void SetMessageVariables(const FieldDescriptor* descriptor,
                          map<string, string>* variables) {
-  (*variables)["name"] = FieldName(descriptor);
+  SetCommonFieldVariables(descriptor, variables);
   (*variables)["type"] = ClassName(descriptor->message_type(), true);
-  (*variables)["index"] = SimpleItoa(descriptor->index());
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
-  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
-  (*variables)["tag_size"] = SimpleItoa(
-    WireFormat::TagSize(descriptor->number(), descriptor->type()));
 }
 
 }  // namespace
@@ -81,8 +70,8 @@
 void MessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline const $type$& $name$() const;\n"
-    "inline $type$* mutable_$name$();\n");
+    "inline const $type$& $name$() const$deprecation$;\n"
+    "inline $type$* mutable_$name$()$deprecation$;\n");
 }
 
 void MessageFieldGenerator::
@@ -124,35 +113,35 @@
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
       "     input, mutable_$name$()));\n");
   } else {
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual("
-        "$number$, input, mutable_$name$()));\n");
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
+      "      $number$, input, mutable_$name$()));\n");
   }
 }
 
 void MessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
-      "$number$, this->$name$(), output);\n");
+    "::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
+    "  $number$, this->$name$(), output);\n");
 }
 
 void MessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "target = ::google::protobuf::internal::WireFormat::"
-      "Write$declared_type$NoVirtualToArray("
-      "$number$, this->$name$(), target);\n");
+    "target = ::google::protobuf::internal::WireFormatLite::\n"
+    "  Write$declared_type$NoVirtualToArray(\n"
+    "    $number$, this->$name$(), target);\n");
 }
 
 void MessageFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
-    "  ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
+    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
     "    this->$name$());\n");
 }
 
@@ -175,11 +164,13 @@
 void RepeatedMessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const;\n"
-    "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$();\n"
-    "inline const $type$& $name$(int index) const;\n"
-    "inline $type$* mutable_$name$(int index);\n"
-    "inline $type$* add_$name$();\n");
+    "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const"
+                 "$deprecation$;\n"
+    "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$()"
+                 "$deprecation$;\n"
+    "inline const $type$& $name$(int index) const$deprecation$;\n"
+    "inline $type$* mutable_$name$(int index)$deprecation$;\n"
+    "inline $type$* add_$name$()$deprecation$;\n");
 }
 
 void RepeatedMessageFieldGenerator::
@@ -228,12 +219,12 @@
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
-      "     input, add_$name$()));\n");
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+      "      input, add_$name$()));\n");
   } else {
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual("
-        "$number$, input, add_$name$()));\n");
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
+      "      $number$, input, add_$name$()));\n");
   }
 }
 
@@ -241,8 +232,8 @@
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
-    "  ::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
-        "$number$, this->$name$(i), output);\n"
+    "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
+    "    $number$, this->$name$(i), output);\n"
     "}\n");
 }
 
@@ -250,9 +241,9 @@
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
-    "  target = ::google::protobuf::internal::WireFormat::"
-        "Write$declared_type$NoVirtualToArray("
-        "$number$, this->$name$(i), target);\n"
+    "  target = ::google::protobuf::internal::WireFormatLite::\n"
+    "    Write$declared_type$NoVirtualToArray(\n"
+    "      $number$, this->$name$(i), target);\n"
     "}\n");
 }
 
@@ -262,7 +253,7 @@
     "total_size += $tag_size$ * this->$name$_size();\n"
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
     "  total_size +=\n"
-    "    ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
+    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
     "      this->$name$(i));\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 44d0b97..81f5ce0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -35,7 +35,7 @@
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -43,7 +43,7 @@
 namespace compiler {
 namespace cpp {
 
-using internal::WireFormat;
+using internal::WireFormatLite;
 
 namespace {
 
@@ -57,14 +57,14 @@
     case FieldDescriptor::TYPE_UINT64  : return -1;
     case FieldDescriptor::TYPE_SINT32  : return -1;
     case FieldDescriptor::TYPE_SINT64  : return -1;
-    case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size;
-    case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size;
-    case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size;
-    case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size;
-    case FieldDescriptor::TYPE_FLOAT   : return WireFormat::kFloatSize;
-    case FieldDescriptor::TYPE_DOUBLE  : return WireFormat::kDoubleSize;
+    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
+    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
+    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
+    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
+    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
+    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
 
-    case FieldDescriptor::TYPE_BOOL    : return WireFormat::kBoolSize;
+    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
     case FieldDescriptor::TYPE_ENUM    : return -1;
 
     case FieldDescriptor::TYPE_STRING  : return -1;
@@ -79,20 +79,11 @@
   return -1;
 }
 
-// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
-//   repeat code between this and the other field types.
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
                            map<string, string>* variables) {
-  (*variables)["name"] = FieldName(descriptor);
+  SetCommonFieldVariables(descriptor, variables);
   (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
   (*variables)["default"] = DefaultValue(descriptor);
-  (*variables)["index"] = SimpleItoa(descriptor->index());
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
-  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
-  (*variables)["tag_size"] = SimpleItoa(
-    WireFormat::TagSize(descriptor->number(), descriptor->type()));
-
   int fixed_size = FixedSize(descriptor->type());
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
@@ -119,8 +110,8 @@
 void PrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline $type$ $name$() const;\n"
-    "inline void set_$name$($type$ value);\n");
+    "inline $type$ $name$() const$deprecation$;\n"
+    "inline void set_$name$($type$ value)$deprecation$;\n");
 }
 
 void PrimitiveFieldGenerator::
@@ -158,7 +149,7 @@
 void PrimitiveFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
-    "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
+    "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
     "      input, &$name$_));\n"
     "_set_bit($index$);\n");
 }
@@ -166,14 +157,14 @@
 void PrimitiveFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "::google::protobuf::internal::WireFormat::Write$declared_type$("
+    "::google::protobuf::internal::WireFormatLite::Write$declared_type$("
       "$number$, this->$name$(), output);\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
+    "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
       "$number$, this->$name$(), target);\n");
 }
 
@@ -183,7 +174,7 @@
   if (fixed_size == -1) {
     printer->Print(variables_,
       "total_size += $tag_size$ +\n"
-      "  ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
+      "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
       "    this->$name$());\n");
   } else {
     printer->Print(variables_,
@@ -205,8 +196,7 @@
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
     "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
-  if (descriptor_->options().packed() &&
-      descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
     printer->Print(variables_,
       "mutable int _$name$_cached_byte_size_;\n");
   }
@@ -215,11 +205,12 @@
 void RepeatedPrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const;\n"
-    "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$();\n"
-    "inline $type$ $name$(int index) const;\n"
-    "inline void set_$name$(int index, $type$ value);\n"
-    "inline void add_$name$($type$ value);\n");
+    "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const\n"
+    "    $deprecation$;\n"
+    "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$()$deprecation$;\n"
+    "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");
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -272,12 +263,12 @@
     printer->Print(variables_,
       "::google::protobuf::uint32 length;\n"
       "DO_(input->ReadVarint32(&length));\n"
-      "::google::protobuf::io::CodedInputStream::Limit limit = "
-          "input->PushLimit(length);\n"
+      "::google::protobuf::io::CodedInputStream::Limit limit =\n"
+      "    input->PushLimit(length);\n"
       "while (input->BytesUntilLimit() > 0) {\n"
       "  $type$ value;\n"
-      "  DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
-        "input, &value));\n"
+      "  DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+      "        input, &value));\n"
       "  add_$name$(value);\n"
       "}\n"
       "input->PopLimit(limit);\n");
@@ -286,8 +277,8 @@
   } else {
     printer->Print(variables_,
       "$type$ value;\n"
-      "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
-        "input, &value));\n"
+      "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+      "      input, &value));\n"
       "add_$name$(value);\n");
   }
 }
@@ -298,9 +289,9 @@
     // Write the tag and the size.
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
-      "  ::google::protobuf::internal::WireFormat::WriteTag("
+      "  ::google::protobuf::internal::WireFormatLite::WriteTag("
           "$number$, "
-          "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
+          "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
           "output);\n"
       "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
       "}\n");
@@ -309,12 +300,12 @@
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
-      "  ::google::protobuf::internal::WireFormat::Write$declared_type$NoTag("
-          "this->$name$(i), output);\n");
+      "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
+      "    this->$name$(i), output);\n");
   } else {
     printer->Print(variables_,
-      "  ::google::protobuf::internal::WireFormat::Write$declared_type$("
-          "$number$, this->$name$(i), output);\n");
+      "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
+      "    $number$, this->$name$(i), output);\n");
   }
   printer->Print("}\n");
 }
@@ -325,26 +316,24 @@
     // Write the tag and the size.
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
-      "  target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
-          "$number$, "
-          "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
-          "target);\n"
-      "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
-          "_$name$_cached_byte_size_, target);\n"
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
+      "    $number$,\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
+      "    target);\n"
+      "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
+      "    _$name$_cached_byte_size_, target);\n"
       "}\n");
   }
   printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
-      "  target = ::google::protobuf::internal::WireFormat::"
-          "Write$declared_type$NoTagToArray("
-          "this->$name$(i), target);\n");
+      "  target = ::google::protobuf::internal::WireFormatLite::\n"
+      "    Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
   } else {
     printer->Print(variables_,
-      "  target = ::google::protobuf::internal::WireFormat::"
-          "Write$declared_type$ToArray("
-          "$number$, this->$name$(i), target);\n");
+      "  target = ::google::protobuf::internal::WireFormatLite::\n"
+      "    Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
   }
   printer->Print("}\n");
 }
@@ -359,8 +348,8 @@
   if (fixed_size == -1) {
     printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n"
-      "  data_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
-      "    this->$name$(i));\n"
+      "  data_size += ::google::protobuf::internal::WireFormatLite::\n"
+      "    $declared_type$Size(this->$name$(i));\n"
       "}\n");
   } else {
     printer->Print(variables_,
@@ -370,8 +359,8 @@
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
       "if (data_size > 0) {\n"
-      "  total_size += $tag_size$ + "
-        "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
+      "  total_size += $tag_size$ +\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
       "}\n"
       "_$name$_cached_byte_size_ = data_size;\n"
       "total_size += data_size;\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
index 7689fa1..c282568 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -249,7 +249,7 @@
     sub_vars["input_type"] = ClassName(method->input_type(), true);
     sub_vars["output_type"] = ClassName(method->output_type(), true);
 
-    // Note:  ::google::protobuf::down_cast does not work here because it only works on pointers,
+    // Note:  down_cast does not work here because it only works on pointers,
     //   not references.
     printer->Print(sub_vars,
       "    case $index$:\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 05858da..72258e8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -35,7 +35,6 @@
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -44,23 +43,13 @@
 namespace compiler {
 namespace cpp {
 
-using internal::WireFormat;
-
 namespace {
 
-// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
-//   repeat code between this and the other field types.
 void SetStringVariables(const FieldDescriptor* descriptor,
                         map<string, string>* variables) {
-  (*variables)["name"] = FieldName(descriptor);
+  SetCommonFieldVariables(descriptor, variables);
   (*variables)["default"] =
     "\"" + CEscape(descriptor->default_value_string()) + "\"";
-  (*variables)["index"] = SimpleItoa(descriptor->index());
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
-  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
-  (*variables)["tag_size"] = SimpleItoa(
-    WireFormat::TagSize(descriptor->number(), descriptor->type()));
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
 }
@@ -111,11 +100,12 @@
   }
 
   printer->Print(variables_,
-    "inline const ::std::string& $name$() const;\n"
-    "inline void set_$name$(const ::std::string& value);\n"
-    "inline void set_$name$(const char* value);\n"
-    "inline void set_$name$(const $pointer_type$* value, size_t size);\n"
-    "inline ::std::string* mutable_$name$();\n");
+    "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)"
+                 "$deprecation$;\n"
+    "inline ::std::string* mutable_$name$()$deprecation$;\n");
 
   if (descriptor_->options().has_ctype()) {
     printer->Outdent();
@@ -221,29 +211,52 @@
 void StringFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
-    "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
-      "input, mutable_$name$()));\n");
+    "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+    "      input, this->mutable_$name$()));\n");
+  if (HasUtf8Verification(descriptor_->file()) &&
+      descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    printer->Print(variables_,
+      "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
+      "  this->$name$().data(), this->$name$().length(),\n"
+      "  ::google::protobuf::internal::WireFormat::PARSE);\n");
+  }
 }
 
 void StringFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  if (HasUtf8Verification(descriptor_->file()) &&
+      descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    printer->Print(variables_,
+      "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
+      "  this->$name$().data(), this->$name$().length(),\n"
+      "  ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
+  }
   printer->Print(variables_,
-    "::google::protobuf::internal::WireFormat::Write$declared_type$("
-      "$number$, this->$name$(), output);\n");
+    "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
+    "  $number$, this->$name$(), output);\n");
 }
 
 void StringFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  if (HasUtf8Verification(descriptor_->file()) &&
+      descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    printer->Print(variables_,
+      "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
+      "  this->$name$().data(), this->$name$().length(),\n"
+      "  ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
+  }
   printer->Print(variables_,
-    "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
-      "$number$, this->$name$(), target);\n");
+    "target =\n"
+    "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
+    "    $number$, this->$name$(), target);\n");
 }
 
 void StringFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
-    "  ::google::protobuf::internal::WireFormat::$declared_type$Size(this->$name$());\n");
+    "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
+    "    this->$name$());\n");
 }
 
 // ===================================================================
@@ -274,18 +287,22 @@
   }
 
   printer->Print(variables_,
-    "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const;\n"
-    "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$();\n"
-    "inline const ::std::string& $name$(int index) const;\n"
-    "inline ::std::string* mutable_$name$(int index);\n"
-    "inline void set_$name$(int index, const ::std::string& value);\n"
-    "inline void set_$name$(int index, const char* value);\n"
+    "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+                 "$deprecation$;\n"
+    "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+                 "$deprecation$;\n"
+    "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 "
-    "void set_$name$(int index, const $pointer_type$* value, size_t size);\n"
-    "inline ::std::string* add_$name$();\n"
-    "inline void add_$name$(const ::std::string& value);\n"
-    "inline void add_$name$(const char* value);\n"
-    "inline void add_$name$(const $pointer_type$* value, size_t size);\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)"
+                 "$deprecation$;\n");
 
   if (descriptor_->options().has_ctype()) {
     printer->Outdent();
@@ -361,26 +378,48 @@
 void RepeatedStringFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
-    "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
-    "     input, add_$name$()));\n");
+    "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+    "      input, this->add_$name$()));\n");
+  if (HasUtf8Verification(descriptor_->file()) &&
+      descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    printer->Print(variables_,
+      "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
+      "  this->$name$(0).data(), this->$name$(0).length(),\n"
+      "  ::google::protobuf::internal::WireFormat::PARSE);\n");
+  }
 }
 
 void RepeatedStringFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (int i = 0; i < this->$name$_size(); i++) {\n"
-    "  ::google::protobuf::internal::WireFormat::Write$declared_type$("
-        "$number$, this->$name$(i), output);\n"
+    "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  if (HasUtf8Verification(descriptor_->file()) &&
+      descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    printer->Print(variables_,
+      "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
+      "  this->$name$(i).data(), this->$name$(i).length(),\n"
+      "  ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
+  }
+  printer->Print(variables_,
+    "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
+    "    $number$, this->$name$(i), output);\n"
     "}\n");
 }
 
 void RepeatedStringFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (int i = 0; i < this->$name$_size(); i++) {\n"
-    "  target = ::google::protobuf::internal::WireFormat::"
-        "Write$declared_type$ToArray("
-        "$number$, this->$name$(i), target);\n"
+    "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  if (HasUtf8Verification(descriptor_->file()) &&
+      descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    printer->Print(variables_,
+      "  ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
+      "    this->$name$(i).data(), this->$name$(i).length(),\n"
+      "    ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
+  }
+  printer->Print(variables_,
+    "  target = ::google::protobuf::internal::WireFormatLite::\n"
+    "    Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
     "}\n");
 }
 
@@ -389,7 +428,7 @@
   printer->Print(variables_,
     "total_size += $tag_size$ * this->$name$_size();\n"
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
-    "  total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
+    "  total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
     "    this->$name$(i));\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index cabf08f..2b16e85 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -50,11 +50,9 @@
 #include <google/protobuf/unittest_optimize_for.pb.h>
 #include <google/protobuf/unittest_embed_optimize_for.pb.h>
 #include <google/protobuf/test_util.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -75,18 +73,6 @@
 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
 namespace cpp_unittest {
 
-TEST(ExtremeDefaultValues, FloatingPoint) {
-  const unittest::TestExtremeDefaultValues& extreme_default =
-      unittest::TestExtremeDefaultValues::default_instance();
-
-  EXPECT_EQ(0.0f, extreme_default.zero_float());
-  EXPECT_EQ(1.0f, extreme_default.one_float());
-  EXPECT_EQ(1.5f, extreme_default.small_float());
-  EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
-  EXPECT_EQ(-1.5f, extreme_default.negative_float());
-  EXPECT_EQ(2.0e8f, extreme_default.large_float());
-  EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
-}
 
 class MockErrorCollector : public MultiFileErrorCollector {
  public:
@@ -157,6 +143,19 @@
             &message.optional_import_message());
 }
 
+TEST(GeneratedMessageTest, FloatingPointDefaults) {
+  const unittest::TestExtremeDefaultValues& extreme_default =
+      unittest::TestExtremeDefaultValues::default_instance();
+
+  EXPECT_EQ(0.0f, extreme_default.zero_float());
+  EXPECT_EQ(1.0f, extreme_default.one_float());
+  EXPECT_EQ(1.5f, extreme_default.small_float());
+  EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
+  EXPECT_EQ(-1.5f, extreme_default.negative_float());
+  EXPECT_EQ(2.0e8f, extreme_default.large_float());
+  EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
+}
+
 TEST(GeneratedMessageTest, Accessors) {
   // Set every field to a unique value then go back and check all those
   // values.
@@ -710,6 +709,32 @@
 
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
+TEST(GeneratedMessageTest, FieldConstantValues) {
+  unittest::TestRequired message;
+  EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51);
+}
+
+TEST(GeneratedMessageTest, ExtensionConstantValues) {
+  EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000);
+  EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001);
+  EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1);
+  EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16);
+  EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18);
+  EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21);
+  EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31);
+  EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46);
+  EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48);
+  EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
+}
+
 // ===================================================================
 
 TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
@@ -803,6 +828,17 @@
   EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value));
 }
 
+TEST(GeneratedEnumTest, GetEnumDescriptor) {
+  EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(),
+            GetEnumDescriptor<unittest::TestAllTypes::NestedEnum>());
+  EXPECT_EQ(unittest::ForeignEnum_descriptor(),
+            GetEnumDescriptor<unittest::ForeignEnum>());
+  EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(),
+            GetEnumDescriptor<unittest::TestEnumWithDupValue>());
+  EXPECT_EQ(unittest::TestSparseEnum_descriptor(),
+            GetEnumDescriptor<unittest::TestSparseEnum>());
+}
+
 #endif  // PROTOBUF_TEST_NO_DESCRIPTORS
 
 // ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 4aac649..8ade50c 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -67,14 +67,17 @@
 EnumGenerator::~EnumGenerator() {}
 
 void EnumGenerator::Generate(io::Printer* printer) {
-  bool is_own_file =
-    descriptor_->containing_type() == NULL &&
-    descriptor_->file()->options().java_multiple_files();
-  printer->Print(
-    "public $static$ enum $classname$\n"
-    "    implements com.google.protobuf.ProtocolMessageEnum {\n",
-    "static", is_own_file ? "" : "static",
-    "classname", descriptor_->name());
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "public enum $classname$\n"
+      "    implements com.google.protobuf.ProtocolMessageEnum {\n",
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "public enum $classname$\n"
+      "    implements com.google.protobuf.Internal.EnumLite {\n",
+      "classname", descriptor_->name());
+  }
   printer->Indent();
 
   for (int i = 0; i < canonical_values_.size(); i++) {
@@ -126,63 +129,78 @@
     "    default: return null;\n"
     "  }\n"
     "}\n"
-    "\n");
+    "\n"
+    "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+    "    internalGetValueMap() {\n"
+    "  return internalValueMap;\n"
+    "}\n"
+    "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+    "    internalValueMap =\n"
+    "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+    "        public $classname$ findValueByNumber(int number) {\n"
+    "          return $classname$.valueOf(number)\n;"
+    "        }\n"
+    "      };\n"
+    "\n",
+    "classname", descriptor_->name());
 
   // -----------------------------------------------------------------
   // Reflection
 
-  printer->Print(
-    "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
-    "    getValueDescriptor() {\n"
-    "  return getDescriptor().getValues().get(index);\n"
-    "}\n"
-    "public final com.google.protobuf.Descriptors.EnumDescriptor\n"
-    "    getDescriptorForType() {\n"
-    "  return getDescriptor();\n"
-    "}\n"
-    "public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
-    "    getDescriptor() {\n");
-
-  // TODO(kenton):  Cache statically?  Note that we can't access descriptors
-  //   at module init time because it wouldn't work with descriptor.proto, but
-  //   we can cache the value the first time getDescriptor() is called.
-  if (descriptor_->containing_type() == NULL) {
+  if (HasDescriptorMethods(descriptor_)) {
     printer->Print(
-      "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
-      "file", ClassName(descriptor_->file()),
-      "index", SimpleItoa(descriptor_->index()));
-  } else {
+      "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
+      "    getValueDescriptor() {\n"
+      "  return getDescriptor().getValues().get(index);\n"
+      "}\n"
+      "public final com.google.protobuf.Descriptors.EnumDescriptor\n"
+      "    getDescriptorForType() {\n"
+      "  return getDescriptor();\n"
+      "}\n"
+      "public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
+      "    getDescriptor() {\n");
+
+    // TODO(kenton):  Cache statically?  Note that we can't access descriptors
+    //   at module init time because it wouldn't work with descriptor.proto, but
+    //   we can cache the value the first time getDescriptor() is called.
+    if (descriptor_->containing_type() == NULL) {
+      printer->Print(
+        "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
+        "file", ClassName(descriptor_->file()),
+        "index", SimpleItoa(descriptor_->index()));
+    } else {
+      printer->Print(
+        "  return $parent$.getDescriptor().getEnumTypes().get($index$);\n",
+        "parent", ClassName(descriptor_->containing_type()),
+        "index", SimpleItoa(descriptor_->index()));
+    }
+
     printer->Print(
-      "  return $parent$.getDescriptor().getEnumTypes().get($index$);\n",
-      "parent", ClassName(descriptor_->containing_type()),
-      "index", SimpleItoa(descriptor_->index()));
+      "}\n"
+      "\n"
+      "private static final $classname$[] VALUES = {\n"
+      "  ",
+      "classname", descriptor_->name());
+
+    for (int i = 0; i < descriptor_->value_count(); i++) {
+      printer->Print("$name$, ",
+        "name", descriptor_->value(i)->name());
+    }
+
+    printer->Print(
+      "\n"
+      "};\n"
+      "public static $classname$ valueOf(\n"
+      "    com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
+      "  if (desc.getType() != getDescriptor()) {\n"
+      "    throw new java.lang.IllegalArgumentException(\n"
+      "      \"EnumValueDescriptor is not for this type.\");\n"
+      "  }\n"
+      "  return VALUES[desc.getIndex()];\n"
+      "}\n",
+      "classname", descriptor_->name());
   }
 
-  printer->Print(
-    "}\n"
-    "\n"
-    "private static final $classname$[] VALUES = {\n"
-    "  ",
-    "classname", descriptor_->name());
-
-  for (int i = 0; i < descriptor_->value_count(); i++) {
-    printer->Print("$name$, ",
-      "name", descriptor_->value(i)->name());
-  }
-
-  printer->Print(
-    "\n"
-    "};\n"
-    "public static $classname$ valueOf(\n"
-    "    com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
-    "  if (desc.getType() != getDescriptor()) {\n"
-    "    throw new java.lang.IllegalArgumentException(\n"
-    "      \"EnumValueDescriptor is not for this type.\");\n"
-    "  }\n"
-    "  return VALUES[desc.getIndex()];\n"
-    "}\n",
-    "classname", descriptor_->name());
-
   // -----------------------------------------------------------------
 
   printer->Print(
@@ -194,14 +212,16 @@
     "}\n",
     "classname", descriptor_->name());
 
-  // Force the static initialization code for the file to run, since it may
-  // initialize static variables declared in this class.
-  printer->Print(
-    "\n"
-    "static {\n"
-    "  $file$.getDescriptor();\n"
-    "}\n",
-    "file", ClassName(descriptor_->file()));
+  if (HasDescriptorMethods(descriptor_)) {
+    // Force the static initialization code for the file to run, since it may
+    // initialize static variables declared in this class.
+    printer->Print(
+      "\n"
+      "static {\n"
+      "  $file$.getDescriptor();\n"
+      "}\n",
+      "file", ClassName(descriptor_->file()));
+  }
 
   printer->Outdent();
   printer->Print("}\n\n");
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 2153042..dc36e06 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -39,7 +39,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -53,18 +53,13 @@
 //   repeat code between this and the other field types.
 void SetEnumVariables(const FieldDescriptor* descriptor,
                       map<string, string>* variables) {
-  const EnumValueDescriptor* default_value;
-  default_value = descriptor->default_value_enum();
-
-  string type = ClassName(descriptor->enum_type());
-
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["type"] = type;
-  (*variables)["default"] = type + "." + default_value->name();
+  (*variables)["type"] = ClassName(descriptor->enum_type());
+  (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
       internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
@@ -132,10 +127,17 @@
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "int rawValue = input.readEnum();\n"
-    "$type$ value = $type$.valueOf(rawValue);\n"
-    "if (value == null) {\n"
-    "  unknownFields.mergeVarintField($number$, rawValue);\n"
-    "} else {\n"
+    "$type$ value = $type$.valueOf(rawValue);\n");
+  if (HasUnknownFields(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
+      "} else {\n");
+  } else {
+    printer->Print(variables_,
+      "if (value != null) {\n");
+  }
+  printer->Print(variables_,
     "  set$capitalized_name$(value);\n"
     "}\n");
 }
@@ -185,7 +187,7 @@
     "}\n");
 
   if (descriptor_->options().packed() &&
-      descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+      HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
   }
@@ -272,10 +274,17 @@
   // Read and store the enum
   printer->Print(variables_,
     "int rawValue = input.readEnum();\n"
-    "$type$ value = $type$.valueOf(rawValue);\n"
-    "if (value == null) {\n"
-    "  unknownFields.mergeVarintField($number$, rawValue);\n"
-    "} else {\n"
+    "$type$ value = $type$.valueOf(rawValue);\n");
+  if (HasUnknownFields(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
+      "} else {\n");
+  } else {
+    printer->Print(variables_,
+      "if (value != null) {\n");
+  }
+  printer->Print(variables_,
     "  add$capitalized_name$(value);\n"
     "}\n");
 
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 302dcea..4403220 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -42,6 +42,39 @@
 namespace compiler {
 namespace java {
 
+namespace {
+
+const char* TypeName(FieldDescriptor::Type field_type) {
+  switch (field_type) {
+    case FieldDescriptor::TYPE_INT32   : return "INT32";
+    case FieldDescriptor::TYPE_UINT32  : return "UINT32";
+    case FieldDescriptor::TYPE_SINT32  : return "SINT32";
+    case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
+    case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
+    case FieldDescriptor::TYPE_INT64   : return "INT64";
+    case FieldDescriptor::TYPE_UINT64  : return "UINT64";
+    case FieldDescriptor::TYPE_SINT64  : return "SINT64";
+    case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
+    case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
+    case FieldDescriptor::TYPE_FLOAT   : return "FLOAT";
+    case FieldDescriptor::TYPE_DOUBLE  : return "DOUBLE";
+    case FieldDescriptor::TYPE_BOOL    : return "BOOL";
+    case FieldDescriptor::TYPE_STRING  : return "STRING";
+    case FieldDescriptor::TYPE_BYTES   : return "BYTES";
+    case FieldDescriptor::TYPE_ENUM    : return "ENUM";
+    case FieldDescriptor::TYPE_GROUP   : return "GROUP";
+    case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+}
+
 ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor)
   : descriptor_(descriptor) {
   if (descriptor_->extension_scope() != NULL) {
@@ -59,6 +92,7 @@
   vars["containing_type"] = ClassName(descriptor_->containing_type());
   vars["number"] = SimpleItoa(descriptor_->number());
   vars["constant_name"] = FieldConstantName(descriptor_);
+  vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite";
 
   JavaType java_type = GetJavaType(descriptor_);
   string singular_type;
@@ -79,13 +113,13 @@
   if (descriptor_->is_repeated()) {
     printer->Print(vars,
       "public static\n"
-      "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
       "    $containing_type$,\n"
       "    java.util.List<$type$>> $name$;\n");
   } else {
     printer->Print(vars,
       "public static\n"
-      "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
       "    $containing_type$,\n"
       "    $type$> $name$;\n");
   }
@@ -96,34 +130,71 @@
   vars["name"] = UnderscoresToCamelCase(descriptor_);
   vars["scope"] = scope_;
   vars["index"] = SimpleItoa(descriptor_->index());
+  vars["extendee"] = ClassName(descriptor_->containing_type());
+  vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_);
+  vars["number"] = SimpleItoa(descriptor_->number());
+  vars["type_constant"] = TypeName(descriptor_->type());
+  vars["packed"] = descriptor_->options().packed() ? "true" : "false";
+  vars["enum_map"] = "null";
+  vars["prototype"] = "null";
 
   JavaType java_type = GetJavaType(descriptor_);
   string singular_type;
   switch (java_type) {
     case JAVATYPE_MESSAGE:
       vars["type"] = ClassName(descriptor_->message_type());
+      vars["prototype"] = ClassName(descriptor_->message_type()) +
+                          ".getDefaultInstance()";
       break;
     case JAVATYPE_ENUM:
       vars["type"] = ClassName(descriptor_->enum_type());
+      vars["enum_map"] = ClassName(descriptor_->enum_type()) +
+                         ".internalGetValueMap()";
       break;
     default:
       vars["type"] = BoxedPrimitiveTypeName(java_type);
       break;
   }
 
-  if (descriptor_->is_repeated()) {
-    printer->Print(vars,
-      "$scope$.$name$ =\n"
-      "  com.google.protobuf.GeneratedMessage\n"
-      "    .newRepeatedGeneratedExtension(\n"
-      "      $scope$.getDescriptor().getExtensions().get($index$),\n"
-      "      $type$.class);\n");
+  if (HasDescriptorMethods(descriptor_->file())) {
+    if (descriptor_->is_repeated()) {
+      printer->Print(vars,
+        "$scope$.$name$ =\n"
+        "  com.google.protobuf.GeneratedMessage\n"
+        "    .newRepeatedGeneratedExtension(\n"
+        "      $scope$.getDescriptor().getExtensions().get($index$),\n"
+        "      $type$.class);\n");
+    } else {
+      printer->Print(vars,
+        "$scope$.$name$ =\n"
+        "  com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n"
+        "    $scope$.getDescriptor().getExtensions().get($index$),\n"
+        "    $type$.class);\n");
+    }
   } else {
-    printer->Print(vars,
-      "$scope$.$name$ =\n"
-      "  com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n"
-      "    $scope$.getDescriptor().getExtensions().get($index$),\n"
-      "    $type$.class);\n");
+    if (descriptor_->is_repeated()) {
+      printer->Print(vars,
+        "$scope$.$name$ =\n"
+        "  com.google.protobuf.GeneratedMessageLite\n"
+        "    .newRepeatedGeneratedExtension(\n"
+        "      $extendee$.getDefaultInstance(),\n"
+        "      $prototype$,\n"
+        "      $enum_map$,\n"
+        "      $number$,\n"
+        "      com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+        "      $packed$);\n");
+    } else {
+      printer->Print(vars,
+        "$scope$.$name$ =\n"
+        "  com.google.protobuf.GeneratedMessageLite\n"
+        "    .newGeneratedExtension(\n"
+        "      $extendee$.getDefaultInstance(),\n"
+        "      $default$,\n"
+        "      $prototype$,\n"
+        "      $enum_map$,\n"
+        "      $number$,\n"
+        "      com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+    }
   }
 }
 
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 31d75be..0e170b3 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -151,7 +151,9 @@
 
   printer->Print(
     "public static void registerAllExtensions(\n"
-    "    com.google.protobuf.ExtensionRegistry registry) {\n");
+    "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
+    "lite", HasDescriptorMethods(file_) ? "" : "Lite");
+
   printer->Indent();
 
   for (int i = 0; i < file_->extension_count(); i++) {
@@ -195,8 +197,42 @@
 
   printer->Print("\n");
 
-  // -----------------------------------------------------------------
+  if (HasDescriptorMethods(file_)) {
+    GenerateEmbeddedDescriptor(printer);
+  } else {
+    printer->Print(
+      "static {\n");
+    printer->Indent();
 
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      // TODO(kenton):  Reuse MessageGenerator objects?
+      MessageGenerator(file_->message_type(i))
+        .GenerateStaticVariableInitializers(printer);
+    }
+
+    for (int i = 0; i < file_->extension_count(); i++) {
+      // TODO(kenton):  Reuse ExtensionGenerator objects?
+      ExtensionGenerator(file_->extension(i))
+        .GenerateInitializationCode(printer);
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "}\n");
+  }
+
+  // Dummy function we can use to force the static initialization block to
+  // run.  Needed by inner classes.  Cannot be private due to
+  // java_multiple_files option.
+  printer->Print(
+    "\n"
+    "public static void internalForceInit() {}\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
   // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
   // and embed it as a string literal, which is parsed and built into real
   // descriptors at initialization time.  We unfortunately have to put it in
@@ -310,9 +346,6 @@
   printer->Outdent();
   printer->Print(
     "}\n");
-
-  printer->Outdent();
-  printer->Print("}\n");
 }
 
 template<typename GeneratorClass, typename DescriptorClass>
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index f1efd01..cb82cea 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -81,6 +81,8 @@
   string java_package_;
   string classname_;
 
+  void GenerateEmbeddedDescriptor(io::Printer* printer);
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
 
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 51af5f0..8ed3aff 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -45,32 +45,6 @@
 namespace compiler {
 namespace java {
 
-namespace {
-
-// Parses a set of comma-delimited name/value pairs, e.g.:
-//   "foo=bar,baz,qux=corge"
-// parses to the pairs:
-//   ("foo", "bar"), ("baz", ""), ("qux", "corge")
-void ParseOptions(const string& text, vector<pair<string, string> >* output) {
-  vector<string> parts;
-  SplitStringUsing(text, ",", &parts);
-
-  for (int i = 0; i < parts.size(); i++) {
-    string::size_type equals_pos = parts[i].find_first_of('=');
-    pair<string, string> value;
-    if (equals_pos == string::npos) {
-      value.first = parts[i];
-      value.second = "";
-    } else {
-      value.first = parts[i].substr(0, equals_pos);
-      value.second = parts[i].substr(equals_pos + 1);
-    }
-    output->push_back(value);
-  }
-}
-
-}  // namespace
-
 JavaGenerator::JavaGenerator() {}
 JavaGenerator::~JavaGenerator() {}
 
@@ -79,7 +53,7 @@
                              OutputDirectory* output_directory,
                              string* error) const {
   vector<pair<string, string> > options;
-  ParseOptions(parameter, &options);
+  ParseGeneratorParameter(parameter, &options);
 
   // -----------------------------------------------------------------
   // parse generator options
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 6a10765..dc6748e 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -37,6 +37,7 @@
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
 
 namespace google {
 namespace protobuf {
@@ -243,6 +244,72 @@
   return NULL;
 }
 
+bool AllAscii(const string& text) {
+  for (int i = 0; i < text.size(); i++) {
+    if ((text[i] & 0x80) != 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+string DefaultValue(const FieldDescriptor* field) {
+  // Switch on cpp_type since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return SimpleItoa(field->default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      // Need to print as a signed int since Java has no unsigned.
+      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
+    case FieldDescriptor::CPPTYPE_INT64:
+      return SimpleItoa(field->default_value_int64()) + "L";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
+             "L";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return SimpleDtoa(field->default_value_double()) + "D";
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return SimpleFtoa(field->default_value_float()) + "F";
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "true" : "false";
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (field->type() == FieldDescriptor::TYPE_BYTES) {
+        if (field->has_default_value()) {
+          // See comments in Internal.java for gory details.
+          return strings::Substitute(
+            "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
+            CEscape(field->default_value_string()));
+        } else {
+          return "com.google.protobuf.ByteString.EMPTY";
+        }
+      } else {
+        if (AllAscii(field->default_value_string())) {
+          // All chars are ASCII.  In this case CEscape() works fine.
+          return "\"" + CEscape(field->default_value_string()) + "\"";
+        } else {
+          // See comments in Internal.java for gory details.
+          return strings::Substitute(
+            "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
+            CEscape(field->default_value_string()));
+        }
+      }
+
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return ClassName(field->enum_type()) + "." +
+             field->default_value_enum()->name();
+
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return ClassName(field->message_type()) + ".getDefaultInstance()";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index de3f883..f1b643c 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -36,6 +36,7 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 
 #include <string>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 
 namespace google {
@@ -115,6 +116,35 @@
 // types.
 const char* BoxedPrimitiveTypeName(JavaType type);
 
+string DefaultValue(const FieldDescriptor* field);
+
+// Does this message class keep track of unknown fields?
+inline bool HasUnknownFields(const Descriptor* descriptor) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+
+// Does this message class have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+inline bool HasGeneratedMethods(const Descriptor* descriptor) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::CODE_SIZE;
+}
+
+// Does this message class have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const Descriptor* descriptor) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
+  return descriptor->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index c9cbd13..f79546d 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -41,7 +41,7 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/descriptor.pb.h>
 
 namespace google {
@@ -50,6 +50,7 @@
 namespace java {
 
 using internal::WireFormat;
+using internal::WireFormatLite;
 
 namespace {
 
@@ -153,38 +154,41 @@
 MessageGenerator::~MessageGenerator() {}
 
 void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
-  // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
-  // used in the construction of descriptors, we have a tricky bootstrapping
-  // problem.  To help control static initialization order, we make sure all
-  // descriptors and other static data that depends on them are members of
-  // the outermost class in the file.  This way, they will be initialized in
-  // a deterministic order.
+  if (HasDescriptorMethods(descriptor_)) {
+    // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
+    // used in the construction of descriptors, we have a tricky bootstrapping
+    // problem.  To help control static initialization order, we make sure all
+    // descriptors and other static data that depends on them are members of
+    // the outermost class in the file.  This way, they will be initialized in
+    // a deterministic order.
 
-  map<string, string> vars;
-  vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
-  vars["index"] = SimpleItoa(descriptor_->index());
-  vars["classname"] = ClassName(descriptor_);
-  if (descriptor_->containing_type() != NULL) {
-    vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
+    map<string, string> vars;
+    vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+    vars["index"] = SimpleItoa(descriptor_->index());
+    vars["classname"] = ClassName(descriptor_);
+    if (descriptor_->containing_type() != NULL) {
+      vars["parent"] = UniqueFileScopeIdentifier(
+          descriptor_->containing_type());
+    }
+    if (descriptor_->file()->options().java_multiple_files()) {
+      // We can only make these package-private since the classes that use them
+      // are in separate files.
+      vars["private"] = "";
+    } else {
+      vars["private"] = "private ";
+    }
+
+    // The descriptor for this type.
+    printer->Print(vars,
+      "$private$static com.google.protobuf.Descriptors.Descriptor\n"
+      "  internal_$identifier$_descriptor;\n");
+
+    // And the FieldAccessorTable.
+    printer->Print(vars,
+      "$private$static\n"
+      "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+      "    internal_$identifier$_fieldAccessorTable;\n");
   }
-  if (descriptor_->file()->options().java_multiple_files()) {
-    // We can only make these package-private since the classes that use them
-    // are in separate files.
-    vars["private"] = "";
-  } else {
-    vars["private"] = "private ";
-  }
-
-  // The descriptor for this type.
-  printer->Print(vars,
-    "$private$static com.google.protobuf.Descriptors.Descriptor\n"
-    "  internal_$identifier$_descriptor;\n");
-
-  // And the FieldAccessorTable.
-  printer->Print(vars,
-    "$private$static\n"
-    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
-    "    internal_$identifier$_fieldAccessorTable;\n");
 
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -196,41 +200,44 @@
 
 void MessageGenerator::GenerateStaticVariableInitializers(
     io::Printer* printer) {
-  map<string, string> vars;
-  vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
-  vars["index"] = SimpleItoa(descriptor_->index());
-  vars["classname"] = ClassName(descriptor_);
-  if (descriptor_->containing_type() != NULL) {
-    vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
-  }
+  if (HasDescriptorMethods(descriptor_)) {
+    map<string, string> vars;
+    vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+    vars["index"] = SimpleItoa(descriptor_->index());
+    vars["classname"] = ClassName(descriptor_);
+    if (descriptor_->containing_type() != NULL) {
+      vars["parent"] = UniqueFileScopeIdentifier(
+          descriptor_->containing_type());
+    }
 
-  // The descriptor for this type.
-  if (descriptor_->containing_type() == NULL) {
-    printer->Print(vars,
-      "internal_$identifier$_descriptor =\n"
-      "  getDescriptor().getMessageTypes().get($index$);\n");
-  } else {
-    printer->Print(vars,
-      "internal_$identifier$_descriptor =\n"
-      "  internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
-  }
+    // The descriptor for this type.
+    if (descriptor_->containing_type() == NULL) {
+      printer->Print(vars,
+        "internal_$identifier$_descriptor =\n"
+        "  getDescriptor().getMessageTypes().get($index$);\n");
+    } else {
+      printer->Print(vars,
+        "internal_$identifier$_descriptor =\n"
+        "  internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
+    }
 
-  // And the FieldAccessorTable.
-  printer->Print(vars,
-    "internal_$identifier$_fieldAccessorTable = new\n"
-    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
-    "    internal_$identifier$_descriptor,\n"
-    "    new java.lang.String[] { ");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    printer->Print(
-      "\"$field_name$\", ",
-      "field_name",
-        UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
+    // And the FieldAccessorTable.
+    printer->Print(vars,
+      "internal_$identifier$_fieldAccessorTable = new\n"
+      "  com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
+      "    internal_$identifier$_descriptor,\n"
+      "    new java.lang.String[] { ");
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      printer->Print(
+        "\"$field_name$\", ",
+        "field_name",
+          UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
+    }
+    printer->Print("},\n"
+      "    $classname$.class,\n"
+      "    $classname$.Builder.class);\n",
+      "classname", ClassName(descriptor_));
   }
-  printer->Print("},\n"
-    "    $classname$.class,\n"
-    "    $classname$.Builder.class);\n",
-    "classname", ClassName(descriptor_));
 
   // Generate static member initializers for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -252,18 +259,35 @@
     descriptor_->file()->options().java_multiple_files();
 
   if (descriptor_->extension_range_count() > 0) {
-    printer->Print(
-      "public $static$ final class $classname$ extends\n"
-      "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
-      "      $classname$> {\n",
-      "static", is_own_file ? "" : "static",
-      "classname", descriptor_->name());
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public $static$ final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
+        "      $classname$> {\n",
+        "static", is_own_file ? "" : "static",
+        "classname", descriptor_->name());
+    } else {
+      printer->Print(
+        "public $static$ final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
+        "      $classname$> {\n",
+        "static", is_own_file ? "" : "static",
+        "classname", descriptor_->name());
+    }
   } else {
-    printer->Print(
-      "public $static$ final class $classname$ extends\n"
-      "    com.google.protobuf.GeneratedMessage {\n",
-      "static", is_own_file ? "" : "static",
-      "classname", descriptor_->name());
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public $static$ final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessage {\n",
+        "static", is_own_file ? "" : "static",
+        "classname", descriptor_->name());
+    } else {
+      printer->Print(
+        "public $static$ final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessageLite {\n",
+        "static", is_own_file ? "" : "static",
+        "classname", descriptor_->name());
+    }
   }
   printer->Indent();
   printer->Print(
@@ -280,20 +304,23 @@
     "}\n"
     "\n",
     "classname", descriptor_->name());
-  printer->Print(
-    "public static final com.google.protobuf.Descriptors.Descriptor\n"
-    "    getDescriptor() {\n"
-    "  return $fileclass$.internal_$identifier$_descriptor;\n"
-    "}\n"
-    "\n"
-    "@Override\n"
-    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
-    "    internalGetFieldAccessorTable() {\n"
-    "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
-    "}\n"
-    "\n",
-    "fileclass", ClassName(descriptor_->file()),
-    "identifier", UniqueFileScopeIdentifier(descriptor_));
+
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "public static final com.google.protobuf.Descriptors.Descriptor\n"
+      "    getDescriptor() {\n"
+      "  return $fileclass$.internal_$identifier$_descriptor;\n"
+      "}\n"
+      "\n"
+      "@Override\n"
+      "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+      "    internalGetFieldAccessorTable() {\n"
+      "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
+      "}\n"
+      "\n",
+      "fileclass", ClassName(descriptor_->file()),
+      "identifier", UniqueFileScopeIdentifier(descriptor_));
+  }
 
   // Nested types and extensions
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -318,7 +345,7 @@
     printer->Print("\n");
   }
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_)) {
     GenerateIsInitialized(printer);
     GenerateMessageSerializationMethods(printer);
   }
@@ -326,12 +353,23 @@
   GenerateParseFromMethods(printer);
   GenerateBuilder(printer);
 
-  // Force the static initialization code for the file to run, since it may
-  // initialize static variables declared in this class.
+  if (HasDescriptorMethods(descriptor_)) {
+    // Force the static initialization code for the file to run, since it may
+    // initialize static variables declared in this class.
+    printer->Print(
+      "\n"
+      "static {\n"
+      "  $file$.getDescriptor();\n"
+      "}\n",
+      "file", ClassName(descriptor_->file()));
+  }
+
+  // Force initialization of outer class.  Otherwise, nested extensions may
+  // not be initialized.
   printer->Print(
     "\n"
     "static {\n"
-    "  $file$.getDescriptor();\n"
+    "  $file$.internalForceInit();\n"
     "}\n",
     "file", ClassName(descriptor_->file()));
 
@@ -360,9 +398,18 @@
   printer->Indent();
 
   if (descriptor_->extension_range_count() > 0) {
-    printer->Print(
-      "com.google.protobuf.GeneratedMessage.ExtendableMessage\n"
-      "  .ExtensionWriter extensionWriter = newExtensionWriter();\n");
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n"
+        "  .ExtensionWriter extensionWriter =\n"
+        "    newMessageSetExtensionWriter();\n",
+        "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite");
+    } else {
+      printer->Print(
+        "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n"
+        "  .ExtensionWriter extensionWriter = newExtensionWriter();\n",
+        "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite");
+    }
   }
 
   // Merge the fields and the extension ranges, both sorted by field number.
@@ -380,12 +427,14 @@
     }
   }
 
-  if (descriptor_->options().message_set_wire_format()) {
-    printer->Print(
-      "getUnknownFields().writeAsMessageSetTo(output);\n");
-  } else {
-    printer->Print(
-      "getUnknownFields().writeTo(output);\n");
+  if (HasUnknownFields(descriptor_)) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "getUnknownFields().writeAsMessageSetTo(output);\n");
+    } else {
+      printer->Print(
+        "getUnknownFields().writeTo(output);\n");
+    }
   }
 
   printer->Outdent();
@@ -406,16 +455,23 @@
   }
 
   if (descriptor_->extension_range_count() > 0) {
-    printer->Print(
-      "size += extensionsSerializedSize();\n");
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "size += extensionsSerializedSizeAsMessageSet();\n");
+    } else {
+      printer->Print(
+        "size += extensionsSerializedSize();\n");
+    }
   }
 
-  if (descriptor_->options().message_set_wire_format()) {
-    printer->Print(
-      "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
-  } else {
-    printer->Print(
-      "size += getUnknownFields().getSerializedSize();\n");
+  if (HasUnknownFields(descriptor_)) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
+    } else {
+      printer->Print(
+        "size += getUnknownFields().getSerializedSize();\n");
+    }
   }
 
   printer->Outdent();
@@ -439,7 +495,7 @@
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
     "           .buildParsed();\n"
@@ -450,7 +506,7 @@
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    byte[] data,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
     "           .buildParsed();\n"
@@ -461,7 +517,7 @@
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
     "           .buildParsed();\n"
@@ -472,7 +528,7 @@
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "  return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
     "           .buildParsed();\n"
@@ -484,7 +540,7 @@
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
     "           .buildParsed();\n"
@@ -509,32 +565,57 @@
 
 void MessageGenerator::GenerateBuilder(io::Printer* printer) {
   printer->Print(
-    "public static Builder newBuilder() { return new Builder(); }\n"
-    "public Builder newBuilderForType() { return new Builder(); }\n"
+    "public static Builder newBuilder() { return Builder.create(); }\n"
+    "public Builder newBuilderForType() { return newBuilder(); }\n"
     "public static Builder newBuilder($classname$ prototype) {\n"
-    "  return new Builder().mergeFrom(prototype);\n"
+    "  return newBuilder().mergeFrom(prototype);\n"
     "}\n"
     "public Builder toBuilder() { return newBuilder(this); }\n"
     "\n",
     "classname", ClassName(descriptor_));
 
   if (descriptor_->extension_range_count() > 0) {
-    printer->Print(
-      "public static final class Builder extends\n"
-      "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
-      "      $classname$, Builder> {\n",
-      "classname", ClassName(descriptor_));
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public static final class Builder extends\n"
+        "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+        "      $classname$, Builder> {\n",
+        "classname", ClassName(descriptor_));
+    } else {
+      printer->Print(
+        "public static final class Builder extends\n"
+        "    com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
+        "      $classname$, Builder> {\n",
+        "classname", ClassName(descriptor_));
+    }
   } else {
-    printer->Print(
-      "public static final class Builder extends\n"
-      "    com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
-      "classname", ClassName(descriptor_));
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public static final class Builder extends\n"
+        "    com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
+        "classname", ClassName(descriptor_));
+    } else {
+      printer->Print(
+        "public static final class Builder extends\n"
+        "    com.google.protobuf.GeneratedMessageLite.Builder<\n"
+        "      $classname$, Builder> {\n",
+        "classname", ClassName(descriptor_));
+    }
   }
   printer->Indent();
 
+  // By using a threadlocal queue, we do not have to worry about locking when
+  // accessing the queue.  Current JDKs implement this very efficiently, using
+  // no locks themselves to acquire the value when needed.
+  printer->Print(
+    "private static final "
+    "  com.google.protobuf.Internal.ThreadLocalQuickQueue<Builder> builders =\n"
+    "    new com.google.protobuf.Internal.ThreadLocalQuickQueue<Builder>();\n"
+    "\n");
+
   GenerateCommonBuilderMethods(printer);
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_)) {
     GenerateBuilderParsingMethods(printer);
   }
 
@@ -553,10 +634,19 @@
 
 void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
   printer->Print(
+    "private $classname$ result;\n"
+    "\n"
     "// Construct using $classname$.newBuilder()\n"
     "private Builder() {}\n"
     "\n"
-    "$classname$ result = new $classname$();\n"
+    "private static Builder create() {\n"
+    "  Builder builder = builders.get().poll();\n"
+    "  if (builder == null) {\n"
+    "    builder = new Builder();\n"
+    "  }\n"
+    "  builder.result = new $classname$();\n"
+    "  return builder;\n"
+    "}\n"
     "\n"
     "@Override\n"
     "protected $classname$ internalGetResult() {\n"
@@ -565,25 +655,38 @@
     "\n"
     "@Override\n"
     "public Builder clear() {\n"
+    "  if (result == null) {\n"
+    "    throw new IllegalStateException(\n"
+    "      \"Cannot call clear() after build().\");\n"
+    "  }\n"
     "  result = new $classname$();\n"
     "  return this;\n"
     "}\n"
     "\n"
     "@Override\n"
     "public Builder clone() {\n"
-    "  return new Builder().mergeFrom(result);\n"
+    "  return create().mergeFrom(result);\n"
     "}\n"
-    "\n"
-    "@Override\n"
-    "public com.google.protobuf.Descriptors.Descriptor\n"
-    "    getDescriptorForType() {\n"
-    "  return $classname$.getDescriptor();\n"
-    "}\n"
-    "\n"
+    "\n",
+    "classname", ClassName(descriptor_));
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "@Override\n"
+      "public com.google.protobuf.Descriptors.Descriptor\n"
+      "    getDescriptorForType() {\n"
+      "  return $classname$.getDescriptor();\n"
+      "}\n"
+      "\n",
+      "classname", ClassName(descriptor_));
+  }
+  printer->Print(
     "public $classname$ getDefaultInstanceForType() {\n"
     "  return $classname$.getDefaultInstance();\n"
     "}\n"
-    "\n",
+    "\n"
+    "public boolean isInitialized() {\n"
+    "  return result.isInitialized();\n"
+    "}\n",
     "classname", ClassName(descriptor_));
 
   // -----------------------------------------------------------------
@@ -592,8 +695,7 @@
     "public $classname$ build() {\n"
     // If result == null, we'll throw an appropriate exception later.
     "  if (result != null && !isInitialized()) {\n"
-    "    throw new com.google.protobuf.UninitializedMessageException(\n"
-    "      result);\n"
+    "    throw newUninitializedMessageException(result);\n"
     "  }\n"
     "  return buildPartial();\n"
     "}\n"
@@ -601,7 +703,7 @@
     "private $classname$ buildParsed()\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  if (!isInitialized()) {\n"
-    "    throw new com.google.protobuf.UninitializedMessageException(\n"
+    "    throw newUninitializedMessageException(\n"
     "      result).asInvalidProtocolBufferException();\n"
     "  }\n"
     "  return buildPartial();\n"
@@ -610,7 +712,7 @@
     "public $classname$ buildPartial() {\n"
     "  if (result == null) {\n"
     "    throw new IllegalStateException(\n"
-    "      \"build() has already been called on this Builder.\");"
+    "      \"build() has already been called on this Builder.\");\n"
     "  }\n",
     "classname", ClassName(descriptor_));
   printer->Indent();
@@ -623,6 +725,7 @@
   printer->Print(
     "  $classname$ returnMe = result;\n"
     "  result = null;\n"
+    "  builders.get().offer(this);\n"
     "  return returnMe;\n"
     "}\n"
     "\n",
@@ -630,18 +733,25 @@
 
   // -----------------------------------------------------------------
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_)) {
+    // MergeFrom(Message other) requires the ability to distinguish the other
+    // messages type by its descriptor.
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "@Override\n"
+        "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
+        "  if (other instanceof $classname$) {\n"
+        "    return mergeFrom(($classname$)other);\n"
+        "  } else {\n"
+        "    super.mergeFrom(other);\n"
+        "    return this;\n"
+        "  }\n"
+        "}\n"
+        "\n",
+        "classname", ClassName(descriptor_));
+    }
+
     printer->Print(
-      "@Override\n"
-      "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
-      "  if (other instanceof $classname$) {\n"
-      "    return mergeFrom(($classname$)other);\n"
-      "  } else {\n"
-      "    super.mergeFrom(other);\n"
-      "    return this;\n"
-      "  }\n"
-      "}\n"
-      "\n"
       "public Builder mergeFrom($classname$ other) {\n"
       // Optimization:  If other is the default instance, we know none of its
       //   fields are set so we can skip the merge.
@@ -661,8 +771,12 @@
         "  this.mergeExtensionFields(other);\n");
     }
 
+    if (HasUnknownFields(descriptor_)) {
+      printer->Print(
+        "  this.mergeUnknownFields(other.getUnknownFields());\n");
+    }
+
     printer->Print(
-      "  this.mergeUnknownFields(other.getUnknownFields());\n"
       "  return this;\n"
       "}\n"
       "\n");
@@ -678,23 +792,19 @@
   printer->Print(
     "@Override\n"
     "public Builder mergeFrom(\n"
-    "    com.google.protobuf.CodedInputStream input)\n"
-    "    throws java.io.IOException {\n"
-    "  return mergeFrom(input,\n"
-    "    com.google.protobuf.ExtensionRegistry.getEmptyRegistry());\n"
-    "}\n"
-    "\n"
-    "@Override\n"
-    "public Builder mergeFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n");
   printer->Indent();
 
+  if (HasUnknownFields(descriptor_)) {
+    printer->Print(
+      "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+      "  com.google.protobuf.UnknownFieldSet.newBuilder(\n"
+      "    this.getUnknownFields());\n");
+  }
+
   printer->Print(
-    "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
-    "  com.google.protobuf.UnknownFieldSet.newBuilder(\n"
-    "    this.getUnknownFields());\n"
     "while (true) {\n");
   printer->Indent();
 
@@ -703,22 +813,34 @@
     "switch (tag) {\n");
   printer->Indent();
 
-  printer->Print(
-    "case 0:\n"          // zero signals EOF / limit reached
-    "  this.setUnknownFields(unknownFields.build());\n"
-    "  return this;\n"
-    "default: {\n"
-    "  if (!parseUnknownField(input, unknownFields,\n"
-    "                         extensionRegistry, tag)) {\n"
-    "    this.setUnknownFields(unknownFields.build());\n"
-    "    return this;\n"   // it's an endgroup tag
-    "  }\n"
-    "  break;\n"
-    "}\n");
+  if (HasUnknownFields(descriptor_)) {
+    printer->Print(
+      "case 0:\n"          // zero signals EOF / limit reached
+      "  this.setUnknownFields(unknownFields.build());\n"
+      "  return this;\n"
+      "default: {\n"
+      "  if (!parseUnknownField(input, unknownFields,\n"
+      "                         extensionRegistry, tag)) {\n"
+      "    this.setUnknownFields(unknownFields.build());\n"
+      "    return this;\n"   // it's an endgroup tag
+      "  }\n"
+      "  break;\n"
+      "}\n");
+  } else {
+    printer->Print(
+      "case 0:\n"          // zero signals EOF / limit reached
+      "  return this;\n"
+      "default: {\n"
+      "  if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
+      "    return this;\n"   // it's an endgroup tag
+      "  }\n"
+      "  break;\n"
+      "}\n");
+  }
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormat::MakeTag(field->number(),
+    uint32 tag = WireFormatLite::MakeTag(field->number(),
       WireFormat::WireTypeForField(field));
 
     printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 798e860..327c205 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -39,9 +39,8 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
 
 namespace google {
 namespace protobuf {
@@ -49,6 +48,7 @@
 namespace java {
 
 using internal::WireFormat;
+using internal::WireFormatLite;
 
 namespace {
 
@@ -121,16 +121,6 @@
   return NULL;
 }
 
-bool AllPrintableAscii(const string& text) {
-  // Cannot use isprint() because it's locale-specific.  :(
-  for (int i = 0; i < text.size(); i++) {
-    if ((text[i] < 0x20) || text[i] >= 0x7F) {
-      return false;
-    }
-  }
-  return true;
-}
-
 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
 // returns -1.
 int FixedSize(FieldDescriptor::Type type) {
@@ -141,14 +131,14 @@
     case FieldDescriptor::TYPE_UINT64  : return -1;
     case FieldDescriptor::TYPE_SINT32  : return -1;
     case FieldDescriptor::TYPE_SINT64  : return -1;
-    case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size;
-    case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size;
-    case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size;
-    case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size;
-    case FieldDescriptor::TYPE_FLOAT   : return WireFormat::kFloatSize;
-    case FieldDescriptor::TYPE_DOUBLE  : return WireFormat::kDoubleSize;
+    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
+    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
+    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
+    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
+    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
+    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
 
-    case FieldDescriptor::TYPE_BOOL    : return WireFormat::kBoolSize;
+    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
     case FieldDescriptor::TYPE_ENUM    : return -1;
 
     case FieldDescriptor::TYPE_STRING  : return -1;
@@ -163,64 +153,6 @@
   return -1;
 }
 
-string DefaultValue(const FieldDescriptor* field) {
-  // Switch on cpp_type since we need to know which default_value_* method
-  // of FieldDescriptor to call.
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT32:
-      return SimpleItoa(field->default_value_int32());
-    case FieldDescriptor::CPPTYPE_UINT32:
-      // Need to print as a signed int since Java has no unsigned.
-      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
-    case FieldDescriptor::CPPTYPE_INT64:
-      return SimpleItoa(field->default_value_int64()) + "L";
-    case FieldDescriptor::CPPTYPE_UINT64:
-      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
-             "L";
-    case FieldDescriptor::CPPTYPE_DOUBLE:
-      return SimpleDtoa(field->default_value_double()) + "D";
-    case FieldDescriptor::CPPTYPE_FLOAT:
-      return SimpleFtoa(field->default_value_float()) + "F";
-    case FieldDescriptor::CPPTYPE_BOOL:
-      return field->default_value_bool() ? "true" : "false";
-    case FieldDescriptor::CPPTYPE_STRING: {
-      bool isBytes = field->type() == FieldDescriptor::TYPE_BYTES;
-
-      if (!isBytes && AllPrintableAscii(field->default_value_string())) {
-        // All chars are ASCII and printable.  In this case CEscape() works
-        // fine (it will only escape quotes and backslashes).
-        // Note:  If this "optimization" is removed, DescriptorProtos will
-        //   no longer be able to initialize itself due to bootstrapping
-        //   problems.
-        return "\"" + CEscape(field->default_value_string()) + "\"";
-      }
-
-      if (isBytes && !field->has_default_value()) {
-        return "com.google.protobuf.ByteString.EMPTY";
-      }
-
-      // Escaping strings correctly for Java and generating efficient
-      // initializers for ByteStrings are both tricky.  We can sidestep the
-      // whole problem by just grabbing the default value from the descriptor.
-      return strings::Substitute(
-        "(($0) $1.getDescriptor().getFields().get($2).getDefaultValue())",
-        isBytes ? "com.google.protobuf.ByteString" : "java.lang.String",
-        ClassName(field->containing_type()), field->index());
-    }
-
-    case FieldDescriptor::CPPTYPE_ENUM:
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      GOOGLE_LOG(FATAL) << "Can't get here.";
-      return "";
-
-    // No default because we want the compiler to complain if any new
-    // types are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return "";
-}
-
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
                            map<string, string>* variables) {
   (*variables)["name"] =
@@ -285,8 +217,17 @@
     "  return this;\n"
     "}\n"
     "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n"
-    "  result.$name$_ = $default$;\n"
+    "  result.has$capitalized_name$ = false;\n");
+  if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+    // The default value is not a simple literal so we want to avoid executing
+    // it multiple times.  Instead, get the default out of the default instance.
+    printer->Print(variables_,
+      "  result.$name$_ = getDefaultInstance().get$capitalized_name$();\n");
+  } else {
+    printer->Print(variables_,
+      "  result.$name$_ = $default$;\n");
+  }
+  printer->Print(variables_,
     "  return this;\n"
     "}\n");
 }
@@ -355,7 +296,7 @@
     "}\n");
 
   if (descriptor_->options().packed() &&
-      descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+      HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
   }
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index e9e0154..02304d6 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -661,7 +661,7 @@
   GOOGLE_CHECK(uninterpreted_option_field != NULL)
       << "No field named \"uninterpreted_option\" in the Options proto.";
 
-  UninterpretedOption* uninterpreted_option = ::google::protobuf::down_cast<UninterpretedOption*>(
+  UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
       options->GetReflection()->AddMessage(options,
                                            uninterpreted_option_field));
 
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index dd7f28c..f82a345 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -798,7 +798,7 @@
 
 EncodedDescriptorDatabase* generated_database_ = NULL;
 DescriptorPool* generated_pool_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
+GoogleOnceType generated_pool_init_;
 
 void DeleteGeneratedPool() {
   delete generated_database_;
@@ -814,7 +814,7 @@
 }
 
 inline void InitGeneratedPoolOnce() {
-  GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
+  ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
 }
 
 }  // anonymous namespace
@@ -1859,7 +1859,11 @@
   // dependency of this file, it will fail, but will set
   // possible_undeclared_dependency_ to point at that file.  This is only used
   // by AddNotDefinedError() to report a more useful error message.
+  // possible_undeclared_dependency_name_ is the name of the symbol that was
+  // actually found in possible_undeclared_dependency_, which may be a parent
+  // of the symbol actually looked for.
   const FileDescriptor* possible_undeclared_dependency_;
+  string possible_undeclared_dependency_name_;
 
   void AddError(const string& element_name,
                 const Message& descriptor,
@@ -2062,7 +2066,7 @@
                                 Message* options);
 
     // A recursive helper function that drills into the intermediate fields
-    // in unknown_fields to check if field #field_number is set on the
+    // in unknown_fields to check if field innermost_field is set on the
     // innermost message. Returns false and sets an error if so.
     bool ExamineIfOptionIsSet(
         vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
@@ -2233,8 +2237,9 @@
              "\"" + undefined_symbol + "\" is not defined.");
   } else {
     AddError(element_name, descriptor, location,
-             "\"" + undefined_symbol + "\" seems to be defined in \""
-             + possible_undeclared_dependency_->name() + "\", which is not "
+             "\"" + possible_undeclared_dependency_name_ +
+             "\" seems to be defined in \"" +
+             possible_undeclared_dependency_->name() + "\", which is not "
              "imported by \"" + filename_ + "\".  To use it here, please "
              "add the necessary import.");
   }
@@ -2295,11 +2300,16 @@
     // symbol unless none of the dependencies define it.
     if (IsInPackage(file_, name)) return result;
     for (int i = 0; i < file_->dependency_count(); i++) {
-      if (IsInPackage(file_->dependency(i), name)) return result;
+      // Note:  A dependency may be NULL if it was not found or had errors.
+      if (file_->dependency(i) != NULL &&
+          IsInPackage(file_->dependency(i), name)) {
+        return result;
+      }
     }
   }
 
   possible_undeclared_dependency_ = file;
+  possible_undeclared_dependency_name_ = name;
   return kNullSymbol;
 }
 
@@ -3592,12 +3602,38 @@
                             proto.array_name(i));                  \
   }
 
+// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
+// avoid problems that exist at init time.
+static bool IsLite(const FileDescriptor* file) {
+  // TODO(kenton):  I don't even remember how many of these conditions are
+  //   actually possible.  I'm just being super-safe.
+  return file != NULL &&
+         &file->options() != NULL &&
+         &file->options() != &FileOptions::default_instance() &&
+         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
+}
+
 void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
                                             const FileDescriptorProto& proto) {
   VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
   VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
   VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
   VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
+
+  // Lite files can only be imported by other Lite files.
+  if (!IsLite(file)) {
+    for (int i = 0; i < file->dependency_count(); i++) {
+      if (IsLite(file->dependency(i))) {
+        AddError(
+          file->name(), proto,
+          DescriptorPool::ErrorCollector::OTHER,
+          "Files that do not use optimize_for = LITE_RUNTIME cannot import "
+          "files which do use this option.  This file is not lite, but it "
+          "imports \"" + file->dependency(i)->name() + "\" which is.");
+        break;
+      }
+    }
+  }
 }
 
 void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
@@ -3647,6 +3683,17 @@
                "MessageSets cannot have fields, only extensions.");
     }
   }
+
+  // Lite extensions can only be of Lite types.
+  if (IsLite(field->file()) &&
+      field->containing_type_ != NULL &&
+      !IsLite(field->containing_type()->file())) {
+    AddError(field->full_name(), proto,
+             DescriptorPool::ErrorCollector::EXTENDEE,
+             "Extensions to non-lite types can only be declared in non-lite "
+             "files.  Note that you cannot extend a non-lite type to contain "
+             "a lite type, but the reverse is allowed.");
+  }
 }
 
 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
@@ -3660,6 +3707,12 @@
 }
 void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
     const ServiceDescriptorProto& proto) {
+  if (IsLite(service->file())) {
+    AddError(service->full_name(), proto,
+             DescriptorPool::ErrorCollector::NAME,
+             "Files with optimize_for = LITE_RUNTIME cannot define services.");
+  }
+
   VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
 }
 
@@ -3761,7 +3814,7 @@
   const int num_uninterpreted_options = original_options->GetReflection()->
       FieldSize(*original_options, original_uninterpreted_options_field);
   for (int i = 0; i < num_uninterpreted_options; ++i) {
-    uninterpreted_option_ = ::google::protobuf::down_cast<const UninterpretedOption*>(
+    uninterpreted_option_ = down_cast<const UninterpretedOption*>(
         &original_options->GetReflection()->GetRepeatedMessage(
             *original_options, original_uninterpreted_options_field, i));
     if (!InterpretSingleOption(options)) {
@@ -4009,14 +4062,13 @@
       const UnknownField* unknown_field = &unknown_fields.field(i);
       FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
       // Recurse into the next submessage.
-      ++intermediate_fields_iter;
       switch (type) {
         case FieldDescriptor::TYPE_MESSAGE:
           if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
             UnknownFieldSet intermediate_unknown_fields;
             if (intermediate_unknown_fields.ParseFromString(
                     unknown_field->length_delimited()) &&
-                !ExamineIfOptionIsSet(intermediate_fields_iter,
+                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
                                       intermediate_fields_end,
                                       innermost_field, debug_msg_name,
                                       intermediate_unknown_fields)) {
@@ -4027,7 +4079,7 @@
 
         case FieldDescriptor::TYPE_GROUP:
           if (unknown_field->type() == UnknownField::TYPE_GROUP) {
-            if (!ExamineIfOptionIsSet(intermediate_fields_iter,
+            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
                                       intermediate_fields_end,
                                       innermost_field, debug_msg_name,
                                       unknown_field->group())) {
@@ -4139,7 +4191,7 @@
                              option_field->full_name() + "\".");
       }
       unknown_fields->AddFixed32(option_field->number(),
-          google::protobuf::internal::WireFormat::EncodeFloat(value));
+          google::protobuf::internal::WireFormatLite::EncodeFloat(value));
       break;
     }
 
@@ -4156,7 +4208,7 @@
                              option_field->full_name() + "\".");
       }
       unknown_fields->AddFixed64(option_field->number(),
-          google::protobuf::internal::WireFormat::EncodeDouble(value));
+          google::protobuf::internal::WireFormatLite::EncodeDouble(value));
       break;
     }
 
@@ -4267,7 +4319,7 @@
 
     case FieldDescriptor::TYPE_SINT32:
       unknown_fields->AddVarint(number,
-          google::protobuf::internal::WireFormat::ZigZagEncode32(value));
+          google::protobuf::internal::WireFormatLite::ZigZagEncode32(value));
       break;
 
     default:
@@ -4289,7 +4341,7 @@
 
     case FieldDescriptor::TYPE_SINT64:
       unknown_fields->AddVarint(number,
-          google::protobuf::internal::WireFormat::ZigZagEncode64(value));
+          google::protobuf::internal::WireFormatLite::ZigZagEncode64(value));
       break;
 
     default:
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 0caed83..a68a6a4 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -1,11 +1,13 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
 #include "google/protobuf/descriptor.pb.h"
 #include <google/protobuf/stubs/once.h>
-#include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 
 namespace google {
 namespace protobuf {
@@ -268,8 +270,9 @@
       sizeof(FileOptions));
   FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0);
   MessageOptions_descriptor_ = file->message_type(9);
-  static const int MessageOptions_offsets_[2] = {
+  static const int MessageOptions_offsets_[3] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_),
   };
   MessageOptions_reflection_ =
@@ -409,7 +412,7 @@
                  &protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto);
 }
 
-void protobuf_RegisterTypes() {
+void protobuf_RegisterTypes(const ::std::string&) {
   protobuf_AssignDescriptorsOnce();
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
     FileDescriptorSet_descriptor_, &FileDescriptorSet::default_instance());
@@ -549,42 +552,43 @@
     "ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030"
     "\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type"
     "\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu"
-    "f.MethodOptions\"\247\002\n\013FileOptions\022\024\n\014java_"
+    "f.MethodOptions\"\271\002\n\013FileOptions\022\024\n\014java_"
     "package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 "
     "\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022"
     "F\n\014optimize_for\030\t \001(\0162).google.protobuf."
     "FileOptions.OptimizeMode:\005SPEED\022C\n\024unint"
     "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
-    ".UninterpretedOption\"(\n\014OptimizeMode\022\t\n\005"
-    "SPEED\020\001\022\r\n\tCODE_SIZE\020\002*\t\010\350\007\020\200\200\200\200\002\"\210\001\n\016Me"
-    "ssageOptions\022&\n\027message_set_wire_format\030"
-    "\001 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 "
+    ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005"
+    "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003"
+    "*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n\027messag"
+    "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
+    "ndard_descriptor_accessor\030\002 \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\"\200"
+    "\002\n\014FieldOptions\0222\n\005ctype\030\001 \001(\0162#.google."
+    "protobuf.FieldOptions.CType\022\016\n\006packed\030\002 "
+    "\001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experi"
+    "mental_map_key\030\t \001(\t\022C\n\024uninterpreted_op"
+    "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+    "tedOption\"#\n\005CType\022\010\n\004CORD\020\001\022\020\n\014STRING_P"
+    "IECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024unin"
+    "terpreted_option\030\347\007 \003(\0132$.google.protobu"
+    "f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020Enum"
+    "ValueOptions\022C\n\024uninterpreted_option\030\347\007 "
     "\003(\0132$.google.protobuf.UninterpretedOptio"
-    "n*\t\010\350\007\020\200\200\200\200\002\"\200\002\n\014FieldOptions\0222\n\005ctype\030\001"
-    " \001(\0162#.google.protobuf.FieldOptions.CTyp"
-    "e\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005f"
-    "alse\022\034\n\024experimental_map_key\030\t \001(\t\022C\n\024un"
-    "interpreted_option\030\347\007 \003(\0132$.google.proto"
-    "buf.UninterpretedOption\"#\n\005CType\022\010\n\004CORD"
-    "\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumO"
-    "ptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
-    "google.protobuf.UninterpretedOption*\t\010\350\007"
-    "\020\200\200\200\200\002\"b\n\020EnumValueOptions\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\016ServiceOpt"
-    "ions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
-    "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
-    "\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted_o"
-    "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr"
-    "etedOption*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedO"
-    "ption\022;\n\004name\030\002 \003(\0132-.google.protobuf.Un"
-    "interpretedOption.NamePart\022\030\n\020identifier"
-    "_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004"
-    "\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_v"
-    "alue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010Name"
-    "Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030"
-    "\002 \002(\010B)\n\023com.google.protobufB\020Descriptor"
-    "ProtosH\001", 3488);
+    "n*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninte"
+    "rpreted_option\030\347\007 \003(\0132$.google.protobuf."
+    "UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethod"
+    "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$"
+    ".google.protobuf.UninterpretedOption*\t\010\350"
+    "\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;\n\004name\030"
+    "\002 \003(\0132-.google.protobuf.UninterpretedOpt"
+    "ion.NamePart\022\030\n\020identifier_value\030\003 \001(\t\022\032"
+    "\n\022positive_int_value\030\004 \001(\004\022\032\n\022negative_i"
+    "nt_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014"
+    "string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n\tname_p"
+    "art\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)\n\023com.g"
+    "oogle.protobufB\020DescriptorProtosH\001", 3554);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
   FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -640,15 +644,14 @@
 const int FileDescriptorSet::kFileFieldNumber;
 #endif  // !_MSC_VER
 
-FileDescriptorSet::FileDescriptorSet()
-  : ::google::protobuf::Message() {
+FileDescriptorSet::FileDescriptorSet() {
   SharedCtor();
 }
 
-void FileDescriptorSet::InitAsDefaultInstance() {}
+void FileDescriptorSet::InitAsDefaultInstance() {
+}
 
-FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
-  : ::google::protobuf::Message() {
+FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -693,16 +696,16 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_file:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_file()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_file()));
         if (input->ExpectTag(10)) goto parse_file;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -710,8 +713,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -734,7 +737,8 @@
   
   // repeated .google.protobuf.FileDescriptorProto file = 1;
   for (int i = 0; i < this->file_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(1, this->file(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      1, this->file(i), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -747,7 +751,9 @@
     ::google::protobuf::uint8* target) const {
   // repeated .google.protobuf.FileDescriptorProto file = 1;
   for (int i = 0; i < this->file_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(1, this->file(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->file(i), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -764,7 +770,7 @@
   total_size += 1 * this->file_size();
   for (int i = 0; i < this->file_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->file(i));
   }
   
@@ -824,14 +830,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* FileDescriptorSet::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FileDescriptorSet_descriptor_;
+  metadata.reflection = FileDescriptorSet_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* FileDescriptorSet::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return FileDescriptorSet_reflection_;
-}
 
 // ===================================================================
 
@@ -848,16 +854,15 @@
 const int FileDescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-FileDescriptorProto::FileDescriptorProto()
-  : ::google::protobuf::Message() {
+FileDescriptorProto::FileDescriptorProto() {
   SharedCtor();
 }
 
-void FileDescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
+void FileDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
 }
 
-FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
-  : ::google::protobuf::Message() {
+FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -931,39 +936,50 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(18)) goto parse_package;
         break;
       }
       
       // optional string package = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_package:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_package()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_package()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->package().data(), this->package().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(26)) goto parse_dependency;
         break;
       }
       
       // repeated string dependency = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_dependency:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(
-             input, add_dependency()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->add_dependency()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->dependency(0).data(), this->dependency(0).length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(26)) goto parse_dependency;
         if (input->ExpectTag(34)) goto parse_message_type;
         break;
@@ -971,13 +987,13 @@
       
       // repeated .google.protobuf.DescriptorProto message_type = 4;
       case 4: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_message_type:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_message_type()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_message_type()));
         if (input->ExpectTag(34)) goto parse_message_type;
         if (input->ExpectTag(42)) goto parse_enum_type;
         break;
@@ -985,13 +1001,13 @@
       
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
       case 5: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_enum_type:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_enum_type()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_enum_type()));
         if (input->ExpectTag(42)) goto parse_enum_type;
         if (input->ExpectTag(50)) goto parse_service;
         break;
@@ -999,13 +1015,13 @@
       
       // repeated .google.protobuf.ServiceDescriptorProto service = 6;
       case 6: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_service:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_service()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_service()));
         if (input->ExpectTag(50)) goto parse_service;
         if (input->ExpectTag(58)) goto parse_extension;
         break;
@@ -1013,13 +1029,13 @@
       
       // repeated .google.protobuf.FieldDescriptorProto extension = 7;
       case 7: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_extension:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_extension()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_extension()));
         if (input->ExpectTag(58)) goto parse_extension;
         if (input->ExpectTag(66)) goto parse_options;
         break;
@@ -1027,12 +1043,12 @@
       
       // optional .google.protobuf.FileOptions options = 8;
       case 8: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -1040,8 +1056,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -1064,42 +1080,59 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // optional string package = 2;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteString(2, this->package(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->package().data(), this->package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->package(), output);
   }
   
   // repeated string dependency = 3;
   for (int i = 0; i < this->dependency_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteString(3, this->dependency(i), output);
+  ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+    this->dependency(i).data(), this->dependency(i).length(),
+    ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      3, this->dependency(i), output);
   }
   
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   for (int i = 0; i < this->message_type_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->message_type(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      4, this->message_type(i), output);
   }
   
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   for (int i = 0; i < this->enum_type_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->enum_type(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      5, this->enum_type(i), output);
   }
   
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   for (int i = 0; i < this->service_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->service(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      6, this->service(i), output);
   }
   
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   for (int i = 0; i < this->extension_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->extension(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      7, this->extension(i), output);
   }
   
   // optional .google.protobuf.FileOptions options = 8;
   if (_has_bit(7)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      8, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -1112,42 +1145,66 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // optional string package = 2;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->package(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->package().data(), this->package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->package(), target);
   }
   
   // repeated string dependency = 3;
   for (int i = 0; i < this->dependency_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->dependency(i), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->dependency(i).data(), this->dependency(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(3, this->dependency(i), target);
   }
   
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   for (int i = 0; i < this->message_type_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->message_type(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, this->message_type(i), target);
   }
   
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   for (int i = 0; i < this->enum_type_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(5, this->enum_type(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, this->enum_type(i), target);
   }
   
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   for (int i = 0; i < this->service_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(6, this->service(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, this->service(i), target);
   }
   
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   for (int i = 0; i < this->extension_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(7, this->extension(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        7, this->extension(i), target);
   }
   
   // optional .google.protobuf.FileOptions options = 8;
   if (_has_bit(7)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(8, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        8, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -1164,19 +1221,21 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional string package = 2;
     if (has_package()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->package());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->package());
     }
     
     // optional .google.protobuf.FileOptions options = 8;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -1184,7 +1243,7 @@
   // repeated string dependency = 3;
   total_size += 1 * this->dependency_size();
   for (int i = 0; i < this->dependency_size(); i++) {
-    total_size += ::google::protobuf::internal::WireFormat::StringSize(
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
       this->dependency(i));
   }
   
@@ -1192,7 +1251,7 @@
   total_size += 1 * this->message_type_size();
   for (int i = 0; i < this->message_type_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->message_type(i));
   }
   
@@ -1200,7 +1259,7 @@
   total_size += 1 * this->enum_type_size();
   for (int i = 0; i < this->enum_type_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->enum_type(i));
   }
   
@@ -1208,7 +1267,7 @@
   total_size += 1 * this->service_size();
   for (int i = 0; i < this->service_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->service(i));
   }
   
@@ -1216,7 +1275,7 @@
   total_size += 1 * this->extension_size();
   for (int i = 0; i < this->extension_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->extension(i));
   }
   
@@ -1310,14 +1369,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* FileDescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FileDescriptorProto_descriptor_;
+  metadata.reflection = FileDescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* FileDescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return FileDescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -1326,15 +1385,14 @@
 const int DescriptorProto_ExtensionRange::kEndFieldNumber;
 #endif  // !_MSC_VER
 
-DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
-  : ::google::protobuf::Message() {
+DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() {
   SharedCtor();
 }
 
-void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {}
+void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {
+}
 
-DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
-  : ::google::protobuf::Message() {
+DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -1384,14 +1442,14 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional int32 start = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadInt32(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
               input, &start_));
         _set_bit(0);
         if (input->ExpectTag(16)) goto parse_end;
@@ -1400,12 +1458,12 @@
       
       // optional int32 end = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_end:
-        DO_(::google::protobuf::internal::WireFormat::ReadInt32(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
               input, &end_));
         _set_bit(1);
         if (input->ExpectAtEnd()) return true;
@@ -1414,8 +1472,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -1438,12 +1496,12 @@
   
   // optional int32 start = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteInt32(1, this->start(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
   }
   
   // optional int32 end = 2;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteInt32(2, this->end(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -1456,12 +1514,12 @@
     ::google::protobuf::uint8* target) const {
   // optional int32 start = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(1, this->start(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
   }
   
   // optional int32 end = 2;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(2, this->end(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -1478,14 +1536,14 @@
     // optional int32 start = 1;
     if (has_start()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::Int32Size(
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->start());
     }
     
     // optional int32 end = 2;
     if (has_end()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::Int32Size(
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->end());
     }
     
@@ -1551,14 +1609,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = DescriptorProto_ExtensionRange_descriptor_;
+  metadata.reflection = DescriptorProto_ExtensionRange_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* DescriptorProto_ExtensionRange::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return DescriptorProto_ExtensionRange_reflection_;
-}
 
 // -------------------------------------------------------------------
 
@@ -1573,16 +1631,15 @@
 const int DescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-DescriptorProto::DescriptorProto()
-  : ::google::protobuf::Message() {
+DescriptorProto::DescriptorProto() {
   SharedCtor();
 }
 
-void DescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance());
+void DescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance());
 }
 
-DescriptorProto::DescriptorProto(const DescriptorProto& from)
-  : ::google::protobuf::Message() {
+DescriptorProto::DescriptorProto(const DescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -1647,27 +1704,31 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(18)) goto parse_field;
         break;
       }
       
       // repeated .google.protobuf.FieldDescriptorProto field = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_field:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_field()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_field()));
         if (input->ExpectTag(18)) goto parse_field;
         if (input->ExpectTag(26)) goto parse_nested_type;
         break;
@@ -1675,13 +1736,13 @@
       
       // repeated .google.protobuf.DescriptorProto nested_type = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_nested_type:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_nested_type()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_nested_type()));
         if (input->ExpectTag(26)) goto parse_nested_type;
         if (input->ExpectTag(34)) goto parse_enum_type;
         break;
@@ -1689,13 +1750,13 @@
       
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
       case 4: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_enum_type:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_enum_type()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_enum_type()));
         if (input->ExpectTag(34)) goto parse_enum_type;
         if (input->ExpectTag(42)) goto parse_extension_range;
         break;
@@ -1703,13 +1764,13 @@
       
       // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
       case 5: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_extension_range:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_extension_range()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_extension_range()));
         if (input->ExpectTag(42)) goto parse_extension_range;
         if (input->ExpectTag(50)) goto parse_extension;
         break;
@@ -1717,13 +1778,13 @@
       
       // repeated .google.protobuf.FieldDescriptorProto extension = 6;
       case 6: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_extension:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_extension()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_extension()));
         if (input->ExpectTag(50)) goto parse_extension;
         if (input->ExpectTag(58)) goto parse_options;
         break;
@@ -1731,12 +1792,12 @@
       
       // optional .google.protobuf.MessageOptions options = 7;
       case 7: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -1744,8 +1805,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -1768,37 +1829,47 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   for (int i = 0; i < this->field_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->field(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      2, this->field(i), output);
   }
   
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   for (int i = 0; i < this->nested_type_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->nested_type(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      3, this->nested_type(i), output);
   }
   
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   for (int i = 0; i < this->enum_type_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->enum_type(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      4, this->enum_type(i), output);
   }
   
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   for (int i = 0; i < this->extension_range_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->extension_range(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      5, this->extension_range(i), output);
   }
   
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   for (int i = 0; i < this->extension_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->extension(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      6, this->extension(i), output);
   }
   
   // optional .google.protobuf.MessageOptions options = 7;
   if (_has_bit(6)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      7, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -1811,37 +1882,54 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   for (int i = 0; i < this->field_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->field(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->field(i), target);
   }
   
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   for (int i = 0; i < this->nested_type_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->nested_type(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->nested_type(i), target);
   }
   
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   for (int i = 0; i < this->enum_type_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->enum_type(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, this->enum_type(i), target);
   }
   
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   for (int i = 0; i < this->extension_range_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(5, this->extension_range(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, this->extension_range(i), target);
   }
   
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   for (int i = 0; i < this->extension_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(6, this->extension(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, this->extension(i), target);
   }
   
   // optional .google.protobuf.MessageOptions options = 7;
   if (_has_bit(6)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(7, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        7, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -1858,13 +1946,14 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional .google.protobuf.MessageOptions options = 7;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -1873,7 +1962,7 @@
   total_size += 1 * this->field_size();
   for (int i = 0; i < this->field_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->field(i));
   }
   
@@ -1881,7 +1970,7 @@
   total_size += 1 * this->extension_size();
   for (int i = 0; i < this->extension_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->extension(i));
   }
   
@@ -1889,7 +1978,7 @@
   total_size += 1 * this->nested_type_size();
   for (int i = 0; i < this->nested_type_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->nested_type(i));
   }
   
@@ -1897,7 +1986,7 @@
   total_size += 1 * this->enum_type_size();
   for (int i = 0; i < this->enum_type_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->enum_type(i));
   }
   
@@ -1905,7 +1994,7 @@
   total_size += 1 * this->extension_range_size();
   for (int i = 0; i < this->extension_range_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->extension_range(i));
   }
   
@@ -1995,14 +2084,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* DescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata DescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = DescriptorProto_descriptor_;
+  metadata.reflection = DescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* DescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return DescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -2095,16 +2184,15 @@
 const int FieldDescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-FieldDescriptorProto::FieldDescriptorProto()
-  : ::google::protobuf::Message() {
+FieldDescriptorProto::FieldDescriptorProto() {
   SharedCtor();
 }
 
-void FieldDescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance());
+void FieldDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance());
 }
 
-FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
-  : ::google::protobuf::Message() {
+FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -2197,38 +2285,46 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(18)) goto parse_extendee;
         break;
       }
       
       // optional string extendee = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_extendee:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_extendee()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_extendee()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->extendee().data(), this->extendee().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(24)) goto parse_number;
         break;
       }
       
       // optional int32 number = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_number:
-        DO_(::google::protobuf::internal::WireFormat::ReadInt32(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
               input, &number_));
         _set_bit(1);
         if (input->ExpectTag(32)) goto parse_label;
@@ -2237,13 +2333,13 @@
       
       // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
       case 4: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_label:
         int value;
-        DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
         if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
           set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
         } else {
@@ -2255,13 +2351,13 @@
       
       // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
       case 5: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_type:
         int value;
-        DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
         if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
           set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
         } else {
@@ -2273,36 +2369,44 @@
       
       // optional string type_name = 6;
       case 6: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_type_name:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_type_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_type_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->type_name().data(), this->type_name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(58)) goto parse_default_value;
         break;
       }
       
       // optional string default_value = 7;
       case 7: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_default_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_default_value()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_default_value()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->default_value().data(), this->default_value().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(66)) goto parse_options;
         break;
       }
       
       // optional .google.protobuf.FieldOptions options = 8;
       case 8: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -2310,8 +2414,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -2334,42 +2438,61 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // optional string extendee = 2;
   if (_has_bit(5)) {
-    ::google::protobuf::internal::WireFormat::WriteString(2, this->extendee(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->extendee().data(), this->extendee().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->extendee(), output);
   }
   
   // optional int32 number = 3;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteInt32(3, this->number(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteEnum(4, this->label(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      4, this->label(), output);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
   if (_has_bit(3)) {
-    ::google::protobuf::internal::WireFormat::WriteEnum(5, this->type(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      5, this->type(), output);
   }
   
   // optional string type_name = 6;
   if (_has_bit(4)) {
-    ::google::protobuf::internal::WireFormat::WriteString(6, this->type_name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->type_name().data(), this->type_name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      6, this->type_name(), output);
   }
   
   // optional string default_value = 7;
   if (_has_bit(6)) {
-    ::google::protobuf::internal::WireFormat::WriteString(7, this->default_value(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->default_value().data(), this->default_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      7, this->default_value(), output);
   }
   
   // optional .google.protobuf.FieldOptions options = 8;
   if (_has_bit(7)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      8, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -2382,42 +2505,66 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // optional string extendee = 2;
   if (_has_bit(5)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->extendee(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->extendee().data(), this->extendee().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->extendee(), target);
   }
   
   // optional int32 number = 3;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(3, this->number(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(4, this->label(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      4, this->label(), target);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
   if (_has_bit(3)) {
-    target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(5, this->type(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      5, this->type(), target);
   }
   
   // optional string type_name = 6;
   if (_has_bit(4)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(6, this->type_name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->type_name().data(), this->type_name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        6, this->type_name(), target);
   }
   
   // optional string default_value = 7;
   if (_has_bit(6)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(7, this->default_value(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->default_value().data(), this->default_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        7, this->default_value(), target);
   }
   
   // optional .google.protobuf.FieldOptions options = 8;
   if (_has_bit(7)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(8, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        8, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -2434,50 +2581,54 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional int32 number = 3;
     if (has_number()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::Int32Size(
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->number());
     }
     
     // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
     if (has_label()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::EnumSize(this->label());
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->label());
     }
     
     // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
     if (has_type()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::EnumSize(this->type());
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
     }
     
     // optional string type_name = 6;
     if (has_type_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->type_name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->type_name());
     }
     
     // optional string extendee = 2;
     if (has_extendee()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->extendee());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->extendee());
     }
     
     // optional string default_value = 7;
     if (has_default_value()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->default_value());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->default_value());
     }
     
     // optional .google.protobuf.FieldOptions options = 8;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -2570,14 +2721,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* FieldDescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FieldDescriptorProto_descriptor_;
+  metadata.reflection = FieldDescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* FieldDescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return FieldDescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -2588,16 +2739,15 @@
 const int EnumDescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-EnumDescriptorProto::EnumDescriptorProto()
-  : ::google::protobuf::Message() {
+EnumDescriptorProto::EnumDescriptorProto() {
   SharedCtor();
 }
 
-void EnumDescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance());
+void EnumDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance());
 }
 
-EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
-  : ::google::protobuf::Message() {
+EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -2658,27 +2808,31 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(18)) goto parse_value;
         break;
       }
       
       // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_value()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_value()));
         if (input->ExpectTag(18)) goto parse_value;
         if (input->ExpectTag(26)) goto parse_options;
         break;
@@ -2686,12 +2840,12 @@
       
       // optional .google.protobuf.EnumOptions options = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -2699,8 +2853,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -2723,17 +2877,23 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   for (int i = 0; i < this->value_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->value(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      2, this->value(i), output);
   }
   
   // optional .google.protobuf.EnumOptions options = 3;
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      3, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -2746,17 +2906,26 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   for (int i = 0; i < this->value_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->value(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->value(i), target);
   }
   
   // optional .google.protobuf.EnumOptions options = 3;
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -2773,13 +2942,14 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional .google.protobuf.EnumOptions options = 3;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -2788,7 +2958,7 @@
   total_size += 1 * this->value_size();
   for (int i = 0; i < this->value_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->value(i));
   }
   
@@ -2861,14 +3031,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* EnumDescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumDescriptorProto_descriptor_;
+  metadata.reflection = EnumDescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* EnumDescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return EnumDescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -2879,16 +3049,15 @@
 const int EnumValueDescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-EnumValueDescriptorProto::EnumValueDescriptorProto()
-  : ::google::protobuf::Message() {
+EnumValueDescriptorProto::EnumValueDescriptorProto() {
   SharedCtor();
 }
 
-void EnumValueDescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance());
+void EnumValueDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance());
 }
 
-EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
-  : ::google::protobuf::Message() {
+EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -2950,26 +3119,30 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(16)) goto parse_number;
         break;
       }
       
       // optional int32 number = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_number:
-        DO_(::google::protobuf::internal::WireFormat::ReadInt32(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
               input, &number_));
         _set_bit(1);
         if (input->ExpectTag(26)) goto parse_options;
@@ -2978,12 +3151,12 @@
       
       // optional .google.protobuf.EnumValueOptions options = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -2991,8 +3164,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -3015,17 +3188,22 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // optional int32 number = 2;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteInt32(2, this->number(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
   }
   
   // optional .google.protobuf.EnumValueOptions options = 3;
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      3, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -3038,17 +3216,24 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // optional int32 number = 2;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(2, this->number(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
   }
   
   // optional .google.protobuf.EnumValueOptions options = 3;
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -3065,20 +3250,21 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional int32 number = 2;
     if (has_number()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::Int32Size(
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->number());
     }
     
     // optional .google.protobuf.EnumValueOptions options = 3;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -3151,14 +3337,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* EnumValueDescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumValueDescriptorProto_descriptor_;
+  metadata.reflection = EnumValueDescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* EnumValueDescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return EnumValueDescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -3169,16 +3355,15 @@
 const int ServiceDescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-ServiceDescriptorProto::ServiceDescriptorProto()
-  : ::google::protobuf::Message() {
+ServiceDescriptorProto::ServiceDescriptorProto() {
   SharedCtor();
 }
 
-void ServiceDescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance());
+void ServiceDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance());
 }
 
-ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
-  : ::google::protobuf::Message() {
+ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -3239,27 +3424,31 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(18)) goto parse_method;
         break;
       }
       
       // repeated .google.protobuf.MethodDescriptorProto method = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_method:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_method()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_method()));
         if (input->ExpectTag(18)) goto parse_method;
         if (input->ExpectTag(26)) goto parse_options;
         break;
@@ -3267,12 +3456,12 @@
       
       // optional .google.protobuf.ServiceOptions options = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -3280,8 +3469,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -3304,17 +3493,23 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   for (int i = 0; i < this->method_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->method(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      2, this->method(i), output);
   }
   
   // optional .google.protobuf.ServiceOptions options = 3;
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      3, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -3327,17 +3522,26 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   for (int i = 0; i < this->method_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->method(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->method(i), target);
   }
   
   // optional .google.protobuf.ServiceOptions options = 3;
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -3354,13 +3558,14 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional .google.protobuf.ServiceOptions options = 3;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -3369,7 +3574,7 @@
   total_size += 1 * this->method_size();
   for (int i = 0; i < this->method_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->method(i));
   }
   
@@ -3442,14 +3647,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* ServiceDescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = ServiceDescriptorProto_descriptor_;
+  metadata.reflection = ServiceDescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* ServiceDescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return ServiceDescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -3463,16 +3668,15 @@
 const int MethodDescriptorProto::kOptionsFieldNumber;
 #endif  // !_MSC_VER
 
-MethodDescriptorProto::MethodDescriptorProto()
-  : ::google::protobuf::Message() {
+MethodDescriptorProto::MethodDescriptorProto() {
   SharedCtor();
 }
 
-void MethodDescriptorProto::InitAsDefaultInstance() {  options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance());
+void MethodDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance());
 }
 
-MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
-  : ::google::protobuf::Message() {
+MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -3550,50 +3754,62 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name().data(), this->name().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(18)) goto parse_input_type;
         break;
       }
       
       // optional string input_type = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_input_type:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_input_type()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_input_type()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->input_type().data(), this->input_type().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(26)) goto parse_output_type;
         break;
       }
       
       // optional string output_type = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_output_type:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_output_type()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_output_type()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->output_type().data(), this->output_type().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(34)) goto parse_options;
         break;
       }
       
       // optional .google.protobuf.MethodOptions options = 4;
       case 4: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_options:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
              input, mutable_options()));
         if (input->ExpectAtEnd()) return true;
         break;
@@ -3601,8 +3817,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -3625,22 +3841,35 @@
   
   // optional string name = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
   }
   
   // optional string input_type = 2;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteString(2, this->input_type(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->input_type().data(), this->input_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->input_type(), output);
   }
   
   // optional string output_type = 3;
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteString(3, this->output_type(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->output_type().data(), this->output_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      3, this->output_type(), output);
   }
   
   // optional .google.protobuf.MethodOptions options = 4;
   if (_has_bit(3)) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->options(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      4, this->options(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -3653,22 +3882,39 @@
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
   }
   
   // optional string input_type = 2;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->input_type(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->input_type().data(), this->input_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->input_type(), target);
   }
   
   // optional string output_type = 3;
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->output_type(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->output_type().data(), this->output_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->output_type(), target);
   }
   
   // optional .google.protobuf.MethodOptions options = 4;
   if (_has_bit(3)) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->options(), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, this->options(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -3685,25 +3931,28 @@
     // optional string name = 1;
     if (has_name()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
     }
     
     // optional string input_type = 2;
     if (has_input_type()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->input_type());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->input_type());
     }
     
     // optional string output_type = 3;
     if (has_output_type()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->output_type());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->output_type());
     }
     
     // optional .google.protobuf.MethodOptions options = 4;
     if (has_options()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
     
@@ -3780,14 +4029,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* MethodDescriptorProto::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = MethodDescriptorProto_descriptor_;
+  metadata.reflection = MethodDescriptorProto_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* MethodDescriptorProto::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return MethodDescriptorProto_reflection_;
-}
 
 // ===================================================================
 
@@ -3799,6 +4048,7 @@
   switch(value) {
     case 1:
     case 2:
+    case 3:
       return true;
     default:
       return false;
@@ -3808,6 +4058,7 @@
 #ifndef _MSC_VER
 const FileOptions_OptimizeMode FileOptions::SPEED;
 const FileOptions_OptimizeMode FileOptions::CODE_SIZE;
+const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME;
 const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN;
 const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
 #endif  // _MSC_VER
@@ -3821,15 +4072,14 @@
 const int FileOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-FileOptions::FileOptions()
-  : ::google::protobuf::Message() {
+FileOptions::FileOptions() {
   SharedCtor();
 }
 
-void FileOptions::InitAsDefaultInstance() {}
+void FileOptions::InitAsDefaultInstance() {
+}
 
-FileOptions::FileOptions(const FileOptions& from)
-  : ::google::protobuf::Message() {
+FileOptions::FileOptions(const FileOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -3899,39 +4149,47 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string java_package = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_java_package()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_java_package()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->java_package().data(), this->java_package().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(66)) goto parse_java_outer_classname;
         break;
       }
       
       // optional string java_outer_classname = 8;
       case 8: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_java_outer_classname:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_java_outer_classname()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_java_outer_classname()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->java_outer_classname().data(), this->java_outer_classname().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(72)) goto parse_optimize_for;
         break;
       }
       
       // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
       case 9: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_optimize_for:
         int value;
-        DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
         if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
           set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
         } else {
@@ -3943,12 +4201,12 @@
       
       // optional bool java_multiple_files = 10 [default = false];
       case 10: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_java_multiple_files:
-        DO_(::google::protobuf::internal::WireFormat::ReadBool(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
               input, &java_multiple_files_));
         _set_bit(2);
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
@@ -3957,13 +4215,13 @@
       
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -3971,8 +4229,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -4000,27 +4258,37 @@
   
   // optional string java_package = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->java_package(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->java_package().data(), this->java_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->java_package(), output);
   }
   
   // optional string java_outer_classname = 8;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteString(8, this->java_outer_classname(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->java_outer_classname().data(), this->java_outer_classname().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      8, this->java_outer_classname(), output);
   }
   
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   if (_has_bit(3)) {
-    ::google::protobuf::internal::WireFormat::WriteEnum(9, this->optimize_for(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      9, this->optimize_for(), output);
   }
   
   // optional bool java_multiple_files = 10 [default = false];
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteBool(10, this->java_multiple_files(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
   }
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -4037,27 +4305,40 @@
     ::google::protobuf::uint8* target) const {
   // optional string java_package = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->java_package(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->java_package().data(), this->java_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->java_package(), target);
   }
   
   // optional string java_outer_classname = 8;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(8, this->java_outer_classname(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->java_outer_classname().data(), this->java_outer_classname().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        8, this->java_outer_classname(), target);
   }
   
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   if (_has_bit(3)) {
-    target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(9, this->optimize_for(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      9, this->optimize_for(), target);
   }
   
   // optional bool java_multiple_files = 10 [default = false];
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(10, this->java_multiple_files(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
   }
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -4078,13 +4359,15 @@
     // optional string java_package = 1;
     if (has_java_package()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->java_package());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->java_package());
     }
     
     // optional string java_outer_classname = 8;
     if (has_java_outer_classname()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->java_outer_classname());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->java_outer_classname());
     }
     
     // optional bool java_multiple_files = 10 [default = false];
@@ -4095,7 +4378,7 @@
     // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
     if (has_optimize_for()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::EnumSize(this->optimize_for());
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
     }
     
   }
@@ -4103,7 +4386,7 @@
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -4186,31 +4469,31 @@
   }
 }
 
-const ::google::protobuf::Descriptor* FileOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata FileOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FileOptions_descriptor_;
+  metadata.reflection = FileOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* FileOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return FileOptions_reflection_;
-}
 
 // ===================================================================
 
 #ifndef _MSC_VER
 const int MessageOptions::kMessageSetWireFormatFieldNumber;
+const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber;
 const int MessageOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-MessageOptions::MessageOptions()
-  : ::google::protobuf::Message() {
+MessageOptions::MessageOptions() {
   SharedCtor();
 }
 
-void MessageOptions::InitAsDefaultInstance() {}
+void MessageOptions::InitAsDefaultInstance() {
+}
 
-MessageOptions::MessageOptions(const MessageOptions& from)
-  : ::google::protobuf::Message() {
+MessageOptions::MessageOptions(const MessageOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -4218,6 +4501,7 @@
 void MessageOptions::SharedCtor() {
   _cached_size_ = 0;
   message_set_wire_format_ = false;
+  no_standard_descriptor_accessor_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -4249,6 +4533,7 @@
   _extensions_.Clear();
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     message_set_wire_format_ = false;
+    no_standard_descriptor_accessor_ = false;
   }
   uninterpreted_option_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -4260,29 +4545,43 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional bool message_set_wire_format = 1 [default = false];
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadBool(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
               input, &message_set_wire_format_));
         _set_bit(0);
+        if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor;
+        break;
+      }
+      
+      // optional bool no_standard_descriptor_accessor = 2 [default = false];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          goto handle_uninterpreted;
+        }
+       parse_no_standard_descriptor_accessor:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
+              input, &no_standard_descriptor_accessor_));
+        _set_bit(1);
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
       
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -4290,8 +4589,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -4319,12 +4618,18 @@
   
   // optional bool message_set_wire_format = 1 [default = false];
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteBool(1, this->message_set_wire_format(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
+  }
+  
+  // optional bool no_standard_descriptor_accessor = 2 [default = false];
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output);
   }
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -4341,12 +4646,19 @@
     ::google::protobuf::uint8* target) const {
   // optional bool message_set_wire_format = 1 [default = false];
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(1, this->message_set_wire_format(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
+  }
+  
+  // optional bool no_standard_descriptor_accessor = 2 [default = false];
+  if (_has_bit(1)) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target);
   }
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -4369,12 +4681,17 @@
       total_size += 1 + 1;
     }
     
+    // optional bool no_standard_descriptor_accessor = 2 [default = false];
+    if (has_no_standard_descriptor_accessor()) {
+      total_size += 1 + 1;
+    }
+    
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -4408,6 +4725,9 @@
     if (from._has_bit(0)) {
       set_message_set_wire_format(from.message_set_wire_format());
     }
+    if (from._has_bit(1)) {
+      set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor());
+    }
   }
   _extensions_.MergeFrom(from._extensions_);
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -4437,6 +4757,7 @@
 void MessageOptions::Swap(MessageOptions* other) {
   if (other != this) {
     std::swap(message_set_wire_format_, other->message_set_wire_format_);
+    std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_);
     uninterpreted_option_.Swap(&other->uninterpreted_option_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
@@ -4445,14 +4766,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* MessageOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata MessageOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = MessageOptions_descriptor_;
+  metadata.reflection = MessageOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* MessageOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return MessageOptions_reflection_;
-}
 
 // ===================================================================
 
@@ -4485,15 +4806,14 @@
 const int FieldOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-FieldOptions::FieldOptions()
-  : ::google::protobuf::Message() {
+FieldOptions::FieldOptions() {
   SharedCtor();
 }
 
-void FieldOptions::InitAsDefaultInstance() {}
+void FieldOptions::InitAsDefaultInstance() {
+}
 
-FieldOptions::FieldOptions(const FieldOptions& from)
-  : ::google::protobuf::Message() {
+FieldOptions::FieldOptions(const FieldOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -4556,15 +4876,15 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional .google.protobuf.FieldOptions.CType ctype = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
         int value;
-        DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
         if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
           set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
         } else {
@@ -4576,12 +4896,12 @@
       
       // optional bool packed = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_packed:
-        DO_(::google::protobuf::internal::WireFormat::ReadBool(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
               input, &packed_));
         _set_bit(1);
         if (input->ExpectTag(24)) goto parse_deprecated;
@@ -4590,12 +4910,12 @@
       
       // optional bool deprecated = 3 [default = false];
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_deprecated:
-        DO_(::google::protobuf::internal::WireFormat::ReadBool(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
               input, &deprecated_));
         _set_bit(2);
         if (input->ExpectTag(74)) goto parse_experimental_map_key;
@@ -4604,25 +4924,29 @@
       
       // optional string experimental_map_key = 9;
       case 9: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_experimental_map_key:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_experimental_map_key()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_experimental_map_key()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->experimental_map_key().data(), this->experimental_map_key().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
       
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -4630,8 +4954,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -4659,27 +4983,33 @@
   
   // optional .google.protobuf.FieldOptions.CType ctype = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteEnum(1, this->ctype(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->ctype(), output);
   }
   
   // optional bool packed = 2;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteBool(2, this->packed(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output);
   }
   
   // optional bool deprecated = 3 [default = false];
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteBool(3, this->deprecated(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
   }
   
   // optional string experimental_map_key = 9;
   if (_has_bit(3)) {
-    ::google::protobuf::internal::WireFormat::WriteString(9, this->experimental_map_key(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->experimental_map_key().data(), this->experimental_map_key().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      9, this->experimental_map_key(), output);
   }
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -4696,27 +5026,35 @@
     ::google::protobuf::uint8* target) const {
   // optional .google.protobuf.FieldOptions.CType ctype = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(1, this->ctype(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->ctype(), target);
   }
   
   // optional bool packed = 2;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(2, this->packed(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target);
   }
   
   // optional bool deprecated = 3 [default = false];
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(3, this->deprecated(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
   }
   
   // optional string experimental_map_key = 9;
   if (_has_bit(3)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(9, this->experimental_map_key(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->experimental_map_key().data(), this->experimental_map_key().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        9, this->experimental_map_key(), target);
   }
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -4737,7 +5075,7 @@
     // optional .google.protobuf.FieldOptions.CType ctype = 1;
     if (has_ctype()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::EnumSize(this->ctype());
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype());
     }
     
     // optional bool packed = 2;
@@ -4753,7 +5091,8 @@
     // optional string experimental_map_key = 9;
     if (has_experimental_map_key()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->experimental_map_key());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->experimental_map_key());
     }
     
   }
@@ -4761,7 +5100,7 @@
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -4844,14 +5183,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* FieldOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata FieldOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FieldOptions_descriptor_;
+  metadata.reflection = FieldOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* FieldOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return FieldOptions_reflection_;
-}
 
 // ===================================================================
 
@@ -4859,15 +5198,14 @@
 const int EnumOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-EnumOptions::EnumOptions()
-  : ::google::protobuf::Message() {
+EnumOptions::EnumOptions() {
   SharedCtor();
 }
 
-void EnumOptions::InitAsDefaultInstance() {}
+void EnumOptions::InitAsDefaultInstance() {
+}
 
-EnumOptions::EnumOptions(const EnumOptions& from)
-  : ::google::protobuf::Message() {
+EnumOptions::EnumOptions(const EnumOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -4913,16 +5251,16 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -4930,8 +5268,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -4959,7 +5297,8 @@
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -4976,7 +5315,9 @@
     ::google::protobuf::uint8* target) const {
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -4997,7 +5338,7 @@
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -5062,14 +5403,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* EnumOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata EnumOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumOptions_descriptor_;
+  metadata.reflection = EnumOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* EnumOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return EnumOptions_reflection_;
-}
 
 // ===================================================================
 
@@ -5077,15 +5418,14 @@
 const int EnumValueOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-EnumValueOptions::EnumValueOptions()
-  : ::google::protobuf::Message() {
+EnumValueOptions::EnumValueOptions() {
   SharedCtor();
 }
 
-void EnumValueOptions::InitAsDefaultInstance() {}
+void EnumValueOptions::InitAsDefaultInstance() {
+}
 
-EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
-  : ::google::protobuf::Message() {
+EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -5131,16 +5471,16 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -5148,8 +5488,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -5177,7 +5517,8 @@
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -5194,7 +5535,9 @@
     ::google::protobuf::uint8* target) const {
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -5215,7 +5558,7 @@
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -5280,14 +5623,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* EnumValueOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata EnumValueOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumValueOptions_descriptor_;
+  metadata.reflection = EnumValueOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* EnumValueOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return EnumValueOptions_reflection_;
-}
 
 // ===================================================================
 
@@ -5295,15 +5638,14 @@
 const int ServiceOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-ServiceOptions::ServiceOptions()
-  : ::google::protobuf::Message() {
+ServiceOptions::ServiceOptions() {
   SharedCtor();
 }
 
-void ServiceOptions::InitAsDefaultInstance() {}
+void ServiceOptions::InitAsDefaultInstance() {
+}
 
-ServiceOptions::ServiceOptions(const ServiceOptions& from)
-  : ::google::protobuf::Message() {
+ServiceOptions::ServiceOptions(const ServiceOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -5349,16 +5691,16 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -5366,8 +5708,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -5395,7 +5737,8 @@
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -5412,7 +5755,9 @@
     ::google::protobuf::uint8* target) const {
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -5433,7 +5778,7 @@
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -5498,14 +5843,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* ServiceOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata ServiceOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = ServiceOptions_descriptor_;
+  metadata.reflection = ServiceOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* ServiceOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return ServiceOptions_reflection_;
-}
 
 // ===================================================================
 
@@ -5513,15 +5858,14 @@
 const int MethodOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
-MethodOptions::MethodOptions()
-  : ::google::protobuf::Message() {
+MethodOptions::MethodOptions() {
   SharedCtor();
 }
 
-void MethodOptions::InitAsDefaultInstance() {}
+void MethodOptions::InitAsDefaultInstance() {
+}
 
-MethodOptions::MethodOptions(const MethodOptions& from)
-  : ::google::protobuf::Message() {
+MethodOptions::MethodOptions(const MethodOptions& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -5567,16 +5911,16 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_uninterpreted_option:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_uninterpreted_option()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_uninterpreted_option()));
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         if (input->ExpectAtEnd()) return true;
         break;
@@ -5584,8 +5928,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         if ((8000u <= tag)) {
@@ -5613,7 +5957,8 @@
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      999, this->uninterpreted_option(i), output);
   }
   
   // Extension range [1000, 536870912)
@@ -5630,7 +5975,9 @@
     ::google::protobuf::uint8* target) const {
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
   }
   
   // Extension range [1000, 536870912)
@@ -5651,7 +5998,7 @@
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
   
@@ -5716,14 +6063,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* MethodOptions::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata MethodOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = MethodOptions_descriptor_;
+  metadata.reflection = MethodOptions_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* MethodOptions::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return MethodOptions_reflection_;
-}
 
 // ===================================================================
 
@@ -5733,15 +6080,14 @@
 const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
 #endif  // !_MSC_VER
 
-UninterpretedOption_NamePart::UninterpretedOption_NamePart()
-  : ::google::protobuf::Message() {
+UninterpretedOption_NamePart::UninterpretedOption_NamePart() {
   SharedCtor();
 }
 
-void UninterpretedOption_NamePart::InitAsDefaultInstance() {}
+void UninterpretedOption_NamePart::InitAsDefaultInstance() {
+}
 
-UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
-  : ::google::protobuf::Message() {
+UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -5798,26 +6144,30 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // required string name_part = 1;
       case 1: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name_part()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_name_part()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->name_part().data(), this->name_part().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(16)) goto parse_is_extension;
         break;
       }
       
       // required bool is_extension = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_is_extension:
-        DO_(::google::protobuf::internal::WireFormat::ReadBool(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
               input, &is_extension_));
         _set_bit(1);
         if (input->ExpectAtEnd()) return true;
@@ -5826,8 +6176,8 @@
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -5850,12 +6200,16 @@
   
   // required string name_part = 1;
   if (_has_bit(0)) {
-    ::google::protobuf::internal::WireFormat::WriteString(1, this->name_part(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name_part().data(), this->name_part().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name_part(), output);
   }
   
   // required bool is_extension = 2;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteBool(2, this->is_extension(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -5868,12 +6222,17 @@
     ::google::protobuf::uint8* target) const {
   // required string name_part = 1;
   if (_has_bit(0)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name_part(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name_part().data(), this->name_part().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name_part(), target);
   }
   
   // required bool is_extension = 2;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(2, this->is_extension(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -5890,7 +6249,8 @@
     // required string name_part = 1;
     if (has_name_part()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->name_part());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name_part());
     }
     
     // required bool is_extension = 2;
@@ -5961,14 +6321,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = UninterpretedOption_NamePart_descriptor_;
+  metadata.reflection = UninterpretedOption_NamePart_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* UninterpretedOption_NamePart::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return UninterpretedOption_NamePart_reflection_;
-}
 
 // -------------------------------------------------------------------
 
@@ -5983,15 +6343,14 @@
 const int UninterpretedOption::kStringValueFieldNumber;
 #endif  // !_MSC_VER
 
-UninterpretedOption::UninterpretedOption()
-  : ::google::protobuf::Message() {
+UninterpretedOption::UninterpretedOption() {
   SharedCtor();
 }
 
-void UninterpretedOption::InitAsDefaultInstance() {}
+void UninterpretedOption::InitAsDefaultInstance() {
+}
 
-UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
-  : ::google::protobuf::Message() {
+UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) {
   SharedCtor();
   MergeFrom(from);
 }
@@ -6062,16 +6421,16 @@
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
-    switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
       case 2: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_name:
-        DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(
-             input, add_name()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_name()));
         if (input->ExpectTag(18)) goto parse_name;
         if (input->ExpectTag(26)) goto parse_identifier_value;
         break;
@@ -6079,24 +6438,28 @@
       
       // optional string identifier_value = 3;
       case 3: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_identifier_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_identifier_value()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_identifier_value()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->identifier_value().data(), this->identifier_value().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
         if (input->ExpectTag(32)) goto parse_positive_int_value;
         break;
       }
       
       // optional uint64 positive_int_value = 4;
       case 4: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_positive_int_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadUInt64(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadUInt64(
               input, &positive_int_value_));
         _set_bit(2);
         if (input->ExpectTag(40)) goto parse_negative_int_value;
@@ -6105,12 +6468,12 @@
       
       // optional int64 negative_int_value = 5;
       case 5: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           goto handle_uninterpreted;
         }
        parse_negative_int_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadInt64(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadInt64(
               input, &negative_int_value_));
         _set_bit(3);
         if (input->ExpectTag(49)) goto parse_double_value;
@@ -6119,12 +6482,12 @@
       
       // optional double double_value = 6;
       case 6: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_FIXED64) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
           goto handle_uninterpreted;
         }
        parse_double_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadDouble(
+        DO_(::google::protobuf::internal::WireFormatLite::ReadDouble(
               input, &double_value_));
         _set_bit(4);
         if (input->ExpectTag(58)) goto parse_string_value;
@@ -6133,20 +6496,21 @@
       
       // optional bytes string_value = 7;
       case 7: {
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
-            ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
           goto handle_uninterpreted;
         }
        parse_string_value:
-        DO_(::google::protobuf::internal::WireFormat::ReadBytes(input, mutable_string_value()));
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+              input, this->mutable_string_value()));
         if (input->ExpectAtEnd()) return true;
         break;
       }
       
       default: {
       handle_uninterpreted:
-        if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -6169,32 +6533,38 @@
   
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   for (int i = 0; i < this->name_size(); i++) {
-    ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->name(i), output);
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      2, this->name(i), output);
   }
   
   // optional string identifier_value = 3;
   if (_has_bit(1)) {
-    ::google::protobuf::internal::WireFormat::WriteString(3, this->identifier_value(), output);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->identifier_value().data(), this->identifier_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      3, this->identifier_value(), output);
   }
   
   // optional uint64 positive_int_value = 4;
   if (_has_bit(2)) {
-    ::google::protobuf::internal::WireFormat::WriteUInt64(4, this->positive_int_value(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output);
   }
   
   // optional int64 negative_int_value = 5;
   if (_has_bit(3)) {
-    ::google::protobuf::internal::WireFormat::WriteInt64(5, this->negative_int_value(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output);
   }
   
   // optional double double_value = 6;
   if (_has_bit(4)) {
-    ::google::protobuf::internal::WireFormat::WriteDouble(6, this->double_value(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output);
   }
   
   // optional bytes string_value = 7;
   if (_has_bit(5)) {
-    ::google::protobuf::internal::WireFormat::WriteBytes(7, this->string_value(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteBytes(
+      7, this->string_value(), output);
   }
   
   if (!unknown_fields().empty()) {
@@ -6207,32 +6577,41 @@
     ::google::protobuf::uint8* target) const {
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   for (int i = 0; i < this->name_size(); i++) {
-    target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->name(i), target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->name(i), target);
   }
   
   // optional string identifier_value = 3;
   if (_has_bit(1)) {
-    target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->identifier_value(), target);
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->identifier_value().data(), this->identifier_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->identifier_value(), target);
   }
   
   // optional uint64 positive_int_value = 4;
   if (_has_bit(2)) {
-    target = ::google::protobuf::internal::WireFormat::WriteUInt64ToArray(4, this->positive_int_value(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target);
   }
   
   // optional int64 negative_int_value = 5;
   if (_has_bit(3)) {
-    target = ::google::protobuf::internal::WireFormat::WriteInt64ToArray(5, this->negative_int_value(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target);
   }
   
   // optional double double_value = 6;
   if (_has_bit(4)) {
-    target = ::google::protobuf::internal::WireFormat::WriteDoubleToArray(6, this->double_value(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target);
   }
   
   // optional bytes string_value = 7;
   if (_has_bit(5)) {
-    target = ::google::protobuf::internal::WireFormat::WriteBytesToArray(7, this->string_value(), target);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+        7, this->string_value(), target);
   }
   
   if (!unknown_fields().empty()) {
@@ -6249,20 +6628,21 @@
     // optional string identifier_value = 3;
     if (has_identifier_value()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::StringSize(this->identifier_value());
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->identifier_value());
     }
     
     // optional uint64 positive_int_value = 4;
     if (has_positive_int_value()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::UInt64Size(
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
           this->positive_int_value());
     }
     
     // optional int64 negative_int_value = 5;
     if (has_negative_int_value()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::Int64Size(
+        ::google::protobuf::internal::WireFormatLite::Int64Size(
           this->negative_int_value());
     }
     
@@ -6274,7 +6654,8 @@
     // optional bytes string_value = 7;
     if (has_string_value()) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormat::BytesSize(this->string_value());
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->string_value());
     }
     
   }
@@ -6282,7 +6663,7 @@
   total_size += 1 * this->name_size();
   for (int i = 0; i < this->name_size(); i++) {
     total_size +=
-      ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->name(i));
   }
   
@@ -6364,14 +6745,14 @@
   }
 }
 
-const ::google::protobuf::Descriptor* UninterpretedOption::GetDescriptor() const {
-  return descriptor();
+::google::protobuf::Metadata UninterpretedOption::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = UninterpretedOption_descriptor_;
+  metadata.reflection = UninterpretedOption_reflection_;
+  return metadata;
 }
 
-const ::google::protobuf::Reflection* UninterpretedOption::GetReflection() const {
-  protobuf_AssignDescriptorsOnce();
-  return UninterpretedOption_reflection_;
-}
 
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 6be8471..782a9ef 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -18,9 +18,10 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
 
 namespace google {
 namespace protobuf {
@@ -69,11 +70,11 @@
   FieldDescriptorProto_Type_TYPE_SINT32 = 17,
   FieldDescriptorProto_Type_TYPE_SINT64 = 18
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
 LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
 const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
 const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
 
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
 inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
   return ::google::protobuf::internal::NameOfEnum(
     FieldDescriptorProto_Type_descriptor(), value);
@@ -88,11 +89,11 @@
   FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
   FieldDescriptorProto_Label_LABEL_REPEATED = 3
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
 LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
 const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
 const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
 
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
 inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
   return ::google::protobuf::internal::NameOfEnum(
     FieldDescriptorProto_Label_descriptor(), value);
@@ -104,13 +105,14 @@
 }
 enum FileOptions_OptimizeMode {
   FileOptions_OptimizeMode_SPEED = 1,
-  FileOptions_OptimizeMode_CODE_SIZE = 2
+  FileOptions_OptimizeMode_CODE_SIZE = 2,
+  FileOptions_OptimizeMode_LITE_RUNTIME = 3
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
 LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
 const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
-const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_CODE_SIZE;
+const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME;
 
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
 inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
   return ::google::protobuf::internal::NameOfEnum(
     FileOptions_OptimizeMode_descriptor(), value);
@@ -124,11 +126,11 @@
   FieldOptions_CType_CORD = 1,
   FieldOptions_CType_STRING_PIECE = 2
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
 LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
 const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
 const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
 
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
 inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
   return ::google::protobuf::internal::NameOfEnum(
     FieldOptions_CType_descriptor(), value);
@@ -187,8 +189,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -212,6 +213,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -277,8 +279,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -384,6 +385,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -449,8 +451,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -479,6 +480,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -544,8 +546,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -635,6 +636,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -700,8 +702,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -724,13 +725,17 @@
   static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
   static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
   static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64;
+  static inline bool Type_IsValid(int value) {
+    return FieldDescriptorProto_Type_IsValid(value);
+  }
+  static const Type Type_MIN =
+    FieldDescriptorProto_Type_Type_MIN;
+  static const Type Type_MAX =
+    FieldDescriptorProto_Type_Type_MAX;
   static inline const ::google::protobuf::EnumDescriptor*
   Type_descriptor() {
     return FieldDescriptorProto_Type_descriptor();
   }
-  static inline bool Type_IsValid(int value) {
-    return FieldDescriptorProto_Type_IsValid(value);
-  }
   static inline const ::std::string& Type_Name(Type value) {
     return FieldDescriptorProto_Type_Name(value);
   }
@@ -738,22 +743,22 @@
       Type* value) {
     return FieldDescriptorProto_Type_Parse(name, value);
   }
-  static const Type Type_MIN =
-    FieldDescriptorProto_Type_Type_MIN;
-  static const Type Type_MAX =
-    FieldDescriptorProto_Type_Type_MAX;
   
   typedef FieldDescriptorProto_Label Label;
   static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
   static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
   static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED;
+  static inline bool Label_IsValid(int value) {
+    return FieldDescriptorProto_Label_IsValid(value);
+  }
+  static const Label Label_MIN =
+    FieldDescriptorProto_Label_Label_MIN;
+  static const Label Label_MAX =
+    FieldDescriptorProto_Label_Label_MAX;
   static inline const ::google::protobuf::EnumDescriptor*
   Label_descriptor() {
     return FieldDescriptorProto_Label_descriptor();
   }
-  static inline bool Label_IsValid(int value) {
-    return FieldDescriptorProto_Label_IsValid(value);
-  }
   static inline const ::std::string& Label_Name(Label value) {
     return FieldDescriptorProto_Label_Name(value);
   }
@@ -761,10 +766,6 @@
       Label* value) {
     return FieldDescriptorProto_Label_Parse(name, value);
   }
-  static const Label Label_MIN =
-    FieldDescriptorProto_Label_Label_MIN;
-  static const Label Label_MAX =
-    FieldDescriptorProto_Label_Label_MAX;
   
   // accessors -------------------------------------------------------
   
@@ -855,6 +856,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -920,8 +922,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -965,6 +966,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1030,8 +1032,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1072,6 +1073,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1137,8 +1139,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1182,6 +1183,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1247,8 +1249,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1305,6 +1306,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1370,21 +1372,25 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
   typedef FileOptions_OptimizeMode OptimizeMode;
   static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
   static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
+  static const OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME;
+  static inline bool OptimizeMode_IsValid(int value) {
+    return FileOptions_OptimizeMode_IsValid(value);
+  }
+  static const OptimizeMode OptimizeMode_MIN =
+    FileOptions_OptimizeMode_OptimizeMode_MIN;
+  static const OptimizeMode OptimizeMode_MAX =
+    FileOptions_OptimizeMode_OptimizeMode_MAX;
   static inline const ::google::protobuf::EnumDescriptor*
   OptimizeMode_descriptor() {
     return FileOptions_OptimizeMode_descriptor();
   }
-  static inline bool OptimizeMode_IsValid(int value) {
-    return FileOptions_OptimizeMode_IsValid(value);
-  }
   static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) {
     return FileOptions_OptimizeMode_Name(value);
   }
@@ -1392,10 +1398,6 @@
       OptimizeMode* value) {
     return FileOptions_OptimizeMode_Parse(name, value);
   }
-  static const OptimizeMode OptimizeMode_MIN =
-    FileOptions_OptimizeMode_OptimizeMode_MIN;
-  static const OptimizeMode OptimizeMode_MAX =
-    FileOptions_OptimizeMode_OptimizeMode_MAX;
   
   // accessors -------------------------------------------------------
   
@@ -1459,6 +1461,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1524,8 +1527,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1538,6 +1540,13 @@
   inline bool message_set_wire_format() const;
   inline 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();
+  static const int kNoStandardDescriptorAccessorFieldNumber = 2;
+  inline bool no_standard_descriptor_accessor() const;
+  inline void set_no_standard_descriptor_accessor(bool value);
+  
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -1555,11 +1564,13 @@
   mutable int _cached_size_;
   
   bool message_set_wire_format_;
+  bool no_standard_descriptor_accessor_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   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();
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   inline bool _has_bit(int index) const {
@@ -1624,21 +1635,24 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
   typedef FieldOptions_CType CType;
   static const CType CORD = FieldOptions_CType_CORD;
   static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
+  static inline bool CType_IsValid(int value) {
+    return FieldOptions_CType_IsValid(value);
+  }
+  static const CType CType_MIN =
+    FieldOptions_CType_CType_MIN;
+  static const CType CType_MAX =
+    FieldOptions_CType_CType_MAX;
   static inline const ::google::protobuf::EnumDescriptor*
   CType_descriptor() {
     return FieldOptions_CType_descriptor();
   }
-  static inline bool CType_IsValid(int value) {
-    return FieldOptions_CType_IsValid(value);
-  }
   static inline const ::std::string& CType_Name(CType value) {
     return FieldOptions_CType_Name(value);
   }
@@ -1646,10 +1660,6 @@
       CType* value) {
     return FieldOptions_CType_Parse(name, value);
   }
-  static const CType CType_MIN =
-    FieldOptions_CType_CType_MIN;
-  static const CType CType_MAX =
-    FieldOptions_CType_CType_MAX;
   
   // accessors -------------------------------------------------------
   
@@ -1709,6 +1719,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1774,8 +1785,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1801,6 +1811,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1866,8 +1877,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1893,6 +1903,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1958,8 +1969,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -1985,6 +1995,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2050,8 +2061,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -2077,6 +2087,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2142,8 +2153,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -2176,6 +2186,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2241,8 +2252,7 @@
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   // nested types ----------------------------------------------------
   
@@ -2316,6 +2326,7 @@
   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();
+  
   ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -3647,6 +3658,22 @@
   message_set_wire_format_ = value;
 }
 
+// optional bool no_standard_descriptor_accessor = 2 [default = false];
+inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
+  return _has_bit(1);
+}
+inline void MessageOptions::clear_no_standard_descriptor_accessor() {
+  no_standard_descriptor_accessor_ = false;
+  _clear_bit(1);
+}
+inline bool MessageOptions::no_standard_descriptor_accessor() const {
+  return no_standard_descriptor_accessor_;
+}
+inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
+  _set_bit(1);
+  no_standard_descriptor_accessor_ = value;
+}
+
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int MessageOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
@@ -4134,4 +4161,30 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() {
+  return ::google::protobuf::FieldDescriptorProto_Type_descriptor();
+}
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() {
+  return ::google::protobuf::FieldDescriptorProto_Label_descriptor();
+}
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() {
+  return ::google::protobuf::FileOptions_OptimizeMode_descriptor();
+}
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() {
+  return ::google::protobuf::FieldOptions_CType_descriptor();
+}
+
+}  // namespace google
+}  // namespace protobuf
+#endif  // SWIG
+
 #endif  // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 381a743..4db88a8 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -247,8 +247,10 @@
 
   // Generated classes can be optimized for speed or code size.
   enum OptimizeMode {
-    SPEED = 1;      // Generate complete code for parsing, serialization, etc.
-    CODE_SIZE = 2;  // Use ReflectionOps to implement these methods.
+    SPEED = 1;        // Generate complete code for parsing, serialization,
+                      // etc.
+    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
+    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
   }
   optional OptimizeMode optimize_for = 9 [default=SPEED];
 
@@ -282,6 +284,11 @@
   // the protocol compiler.
   optional bool message_set_wire_format = 1 [default=false];
 
+  // Disables the generation of the standard "descriptor()" accessor, which can
+  // conflict with a field of the same name.  This is meant to make migration
+  // from proto1 easier; new code should avoid fields named "descriptor".
+  optional bool no_standard_descriptor_accessor = 2 [default=false];
+
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index ce21613..8fcfba3 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -2135,6 +2135,83 @@
   EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
 }
 
+TEST(CustomOptions, MessageOptionThreeFieldsSet) {
+  // This tests a bug which previously existed in custom options parsing.  The
+  // bug occurred when you defined a custom option with message type and then
+  // set three fields of that option on a single definition (see the example
+  // below).  The bug is a bit hard to explain, so check the change history if
+  // you want to know more.
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  protobuf_unittest::TestMessageWithCustomOptions::descriptor()
+    ->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // The following represents the definition:
+  //
+  //   import "google/protobuf/unittest_custom_options.proto"
+  //   package protobuf_unittest;
+  //   message Foo {
+  //     option (complex_opt1).foo  = 1234;
+  //     option (complex_opt1).foo2 = 1234;
+  //     option (complex_opt1).foo3 = 1234;
+  //   }
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"custom_options_import.proto\" "
+    "package: \"protobuf_unittest\" "
+    "dependency: \"google/protobuf/unittest_custom_options.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  options { "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 1234 "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo2\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 1234 "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo3\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 1234 "
+    "    } "
+    "  } "
+    "}",
+    &file_proto));
+
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+  ASSERT_EQ(1, file->message_type_count());
+
+  const MessageOptions& options = file->message_type(0)->options();
+  EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
+}
+
 
 // ===================================================================
 
@@ -2335,6 +2412,30 @@
     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
 }
 
+TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
+  // Used to crash:  If we depend on a non-existent file and then refer to a
+  // package defined in a file that we didn't import, and that package is
+  // nested within a parent package which this file is also in, and we don't
+  // include that parent package in the name (i.e. we do a relative lookup)...
+  // Yes, really.
+  BuildFile(
+    "name: 'foo.proto' "
+    "package: 'outer.foo' ");
+  BuildFileWithErrors(
+    "name: 'bar.proto' "
+    "dependency: 'baz.proto' "
+    "package: 'outer.bar' "
+    "message_type { "
+    "  name: 'Bar' "
+    "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
+    "}",
+
+    "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
+    "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
+      "\"foo.proto\", which is not imported by \"bar.proto\".  To use it here, "
+      "please add the necessary import.\n");
+}
+
 TEST_F(ValidationErrorTest, DupeFile) {
   BuildFile(
     "name: \"foo.proto\" "
@@ -3345,6 +3446,50 @@
     "message type.\n");
 }
 
+TEST_F(ValidationErrorTest, NotLiteImportsLite) {
+  BuildFile(
+    "name: \"bar.proto\" "
+    "options { optimize_for: LITE_RUNTIME } ");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"bar.proto\" ",
+
+    "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
+      "LITE_RUNTIME cannot import files which do use this option.  This file "
+      "is not lite, but it imports \"bar.proto\" which is.\n");
+}
+
+TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type: {"
+    "  name: \"Bar\""
+    "  extension_range { start: 1 end: 1000 }"
+    "}");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"bar.proto\" "
+    "options { optimize_for: LITE_RUNTIME } "
+    "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"Bar\" }",
+
+    "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
+      "declared in non-lite files.  Note that you cannot extend a non-lite "
+      "type to contain a lite type, but the reverse is allowed.\n");
+}
+
+TEST_F(ValidationErrorTest, NoLiteServices) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "options { optimize_for: LITE_RUNTIME } "
+    "service { name: \"Foo\" }",
+
+    "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
+    "define services.\n");
+}
+
 TEST_F(ValidationErrorTest, RollbackAfterError) {
   // Build a file which contains every kind of construct but references an
   // undefined type.  All these constructs will be added to the symbol table
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index be8235e..f8b5b4e 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -70,6 +70,7 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/repeated_field.h>
@@ -82,7 +83,6 @@
 using internal::WireFormat;
 using internal::ExtensionSet;
 using internal::GeneratedMessageReflection;
-using internal::GenericRepeatedField;
 
 
 // ===================================================================
@@ -186,8 +186,7 @@
   int GetCachedSize() const;
   void SetCachedSize(int size) const;
 
-  const Descriptor* GetDescriptor() const;
-  const Reflection* GetReflection() const;
+  Metadata GetMetadata() const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -279,20 +278,10 @@
         break;
 
       case FieldDescriptor::CPPTYPE_MESSAGE: {
-        // If this object is the prototype, its CPPTYPE_MESSAGE fields
-        // must be initialized later, in CrossLinkPrototypes(), so we don't
-        // initialize them here.
-        if (!is_prototype()) {
-          if (!field->is_repeated()) {
-            new(field_ptr) Message*(NULL);
-          } else {
-            const RepeatedPtrField<Message>* prototype_field =
-              reinterpret_cast<const RepeatedPtrField<Message>*>(
-                type_info_->prototype->OffsetToPointer(
-                  type_info_->offsets[i]));
-            new(field_ptr) RepeatedPtrField<Message>(
-              prototype_field->prototype());
-          }
+        if (!field->is_repeated()) {
+          new(field_ptr) Message*(NULL);
+        } else {
+          new(field_ptr) RepeatedPtrField<Message>();
         }
         break;
       }
@@ -322,9 +311,33 @@
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
 
     if (field->is_repeated()) {
-      GenericRepeatedField* field =
-        reinterpret_cast<GenericRepeatedField*>(field_ptr);
-      field->~GenericRepeatedField();
+      switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+        case FieldDescriptor::CPPTYPE_##UPPERCASE :                           \
+          reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr)              \
+              ->~RepeatedField<LOWERCASE>();                                  \
+          break
+
+        HANDLE_TYPE( INT32,  int32);
+        HANDLE_TYPE( INT64,  int64);
+        HANDLE_TYPE(UINT32, uint32);
+        HANDLE_TYPE(UINT64, uint64);
+        HANDLE_TYPE(DOUBLE, double);
+        HANDLE_TYPE( FLOAT,  float);
+        HANDLE_TYPE(  BOOL,   bool);
+        HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+        case FieldDescriptor::CPPTYPE_STRING:
+            reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
+                ->~RepeatedPtrField<string>();
+          break;
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
+              ->~RepeatedPtrField<Message>();
+          break;
+      }
 
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
         string* ptr = *reinterpret_cast<string**>(field_ptr);
@@ -353,24 +366,14 @@
     const FieldDescriptor* field = descriptor->field(i);
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
 
-    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !field->is_repeated()) {
       // For fields with message types, we need to cross-link with the
       // prototype for the field's type.
-      const Message* field_prototype =
+      // For singular fields, the field is just a pointer which should
+      // point to the prototype.
+      *reinterpret_cast<const Message**>(field_ptr) =
         factory->GetPrototype(field->message_type());
-
-      if (field->is_repeated()) {
-        // For repeated fields, we actually construct the RepeatedPtrField
-        // here, but only for fields with message types.  All other repeated
-        // fields are constructed in DynamicMessage's constructor.
-        new(field_ptr) RepeatedPtrField<Message>(field_prototype);
-      } else {
-        // For singular fields, the field is just a pointer which should
-        // point to the prototype.  (OK to const_cast here because the
-        // prototype itself will only be available const to the outside
-        // world.)
-        new(field_ptr) Message*(const_cast<Message*>(field_prototype));
-      }
     }
   }
 }
@@ -392,12 +395,11 @@
   cached_byte_size_ = size;
 }
 
-const Descriptor* DynamicMessage::GetDescriptor() const {
-  return type_info_->type;
-}
-
-const Reflection* DynamicMessage::GetReflection() const {
-  return type_info_->reflection.get();
+Metadata DynamicMessage::GetMetadata() const {
+  Metadata metadata;
+  metadata.descriptor = type_info_->type;
+  metadata.reflection = type_info_->reflection.get();
+  return metadata;
 }
 
 // ===================================================================
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 61b8daa..0f799a5 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -36,14 +36,11 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/extension_set.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
+#include <google/protobuf/message_lite.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/repeated_field.h>
-#include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/stubs/map-util.h>
 
 namespace google {
@@ -52,13 +49,13 @@
 
 namespace {
 
-inline FieldDescriptor::Type real_type(FieldType type) {
-  GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
-  return static_cast<FieldDescriptor::Type>(type);
+inline WireFormatLite::FieldType real_type(FieldType type) {
+  GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
+  return static_cast<WireFormatLite::FieldType>(type);
 }
 
-inline FieldDescriptor::CppType cpp_type(FieldType type) {
-  return FieldDescriptor::TypeToCppType(real_type(type));
+inline WireFormatLite::CppType cpp_type(FieldType type) {
+  return WireFormatLite::FieldTypeToCppType(real_type(type));
 }
 
 // Registry stuff.
@@ -72,13 +69,14 @@
 
   union {
     ExtensionSet::EnumValidityFunc* enum_is_valid;
-    const Message* message_prototype;
+    const MessageLite* message_prototype;
   };
 };
 
-typedef hash_map<pair<const Message*, int>, ExtensionInfo> ExtensionRegistry;
+typedef hash_map<pair<const MessageLite*, int>,
+                 ExtensionInfo> ExtensionRegistry;
 ExtensionRegistry* registry_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
+GoogleOnceType registry_init_;
 
 void DeleteRegistry() {
   delete registry_;
@@ -92,56 +90,58 @@
 
 // This function is only called at startup, so there is no need for thread-
 // safety.
-void Register(const Message* containing_type, int number, ExtensionInfo info) {
-  GoogleOnceInit(&registry_init_, &InitRegistry);
+void Register(const MessageLite* containing_type,
+              int number, ExtensionInfo info) {
+  ::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry);
 
   if (!InsertIfNotPresent(registry_, make_pair(containing_type, number),
                           info)) {
     GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
-               << containing_type->GetDescriptor()->full_name()
+               << containing_type->GetTypeName()
                << "\", field number " << number << ".";
   }
 }
 
 const ExtensionInfo* FindRegisteredExtension(
-    const Message* containing_type, int number) {
+    const MessageLite* containing_type, int number) {
   return (registry_ == NULL) ? NULL :
          FindOrNull(*registry_, make_pair(containing_type, number));
 }
 
 }  // namespace
 
-void ExtensionSet::RegisterExtension(const Message* containing_type,
+void ExtensionSet::RegisterExtension(const MessageLite* containing_type,
                                      int number, FieldType type,
                                      bool is_repeated, bool is_packed) {
-  GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_ENUM);
-  GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_MESSAGE);
-  GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_GROUP);
+  GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM);
+  GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE);
+  GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP);
   ExtensionInfo info(type, is_repeated, is_packed);
   Register(containing_type, number, info);
 }
 
-void ExtensionSet::RegisterEnumExtension(const Message* containing_type,
+void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type,
                                          int number, FieldType type,
                                          bool is_repeated, bool is_packed,
                                          EnumValidityFunc* is_valid) {
-  GOOGLE_CHECK_EQ(type, FieldDescriptor::TYPE_ENUM);
+  GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM);
   ExtensionInfo info(type, is_repeated, is_packed);
   info.enum_is_valid = is_valid;
   Register(containing_type, number, info);
 }
 
-void ExtensionSet::RegisterMessageExtension(const Message* containing_type,
+void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type,
                                             int number, FieldType type,
                                             bool is_repeated, bool is_packed,
-                                            const Message* prototype) {
-  GOOGLE_CHECK(type == FieldDescriptor::TYPE_MESSAGE ||
-        type == FieldDescriptor::TYPE_GROUP);
+                                            const MessageLite* prototype) {
+  GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE ||
+        type == WireFormatLite::TYPE_GROUP);
   ExtensionInfo info(type, is_repeated, is_packed);
   info.message_prototype = prototype;
   Register(containing_type, number, info);
 }
 
+
 // ===================================================================
 // Constructors and basic methods.
 
@@ -154,24 +154,10 @@
   }
 }
 
-void ExtensionSet::AppendToList(const Descriptor* containing_type,
-                                const DescriptorPool* pool,
-                                vector<const FieldDescriptor*>* output) const {
-  for (map<int, Extension>::const_iterator iter = extensions_.begin();
-       iter != extensions_.end(); ++iter) {
-    bool has = false;
-    if (iter->second.is_repeated) {
-      has = iter->second.GetSize() > 0;
-    } else {
-      has = !iter->second.is_cleared;
-    }
-
-    if (has) {
-      output->push_back(
-          pool->FindExtensionByNumber(containing_type, iter->first));
-    }
-  }
-}
+// Defined in extension_set_heavy.cc.
+// void ExtensionSet::AppendToList(const Descriptor* containing_type,
+//                                 const DescriptorPool* pool,
+//                                 vector<const FieldDescriptor*>* output) const
 
 bool ExtensionSet::Has(int number) const {
   map<int, Extension>::const_iterator iter = extensions_.find(number);
@@ -195,11 +181,18 @@
 // ===================================================================
 // Field accessors
 
-#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                            \
-  GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED     \
-                                  : FieldDescriptor::LABEL_OPTIONAL,      \
-            FieldDescriptor::LABEL_##LABEL);                              \
-  GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
+namespace {
+
+enum Cardinality {
+  REPEATED,
+  OPTIONAL
+};
+
+}  // namespace
+
+#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                             \
+  GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED : OPTIONAL, LABEL);         \
+  GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE)
 
 // -------------------------------------------------------------------
 // Primitives
@@ -222,7 +215,7 @@
   Extension* extension;                                                        \
   if (MaybeNewExtension(number, &extension)) {                                 \
     extension->type = type;                                                    \
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_##UPPERCASE);\
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
     extension->is_repeated = false;                                            \
   } else {                                                                     \
     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, UPPERCASE);                              \
@@ -251,7 +244,7 @@
   Extension* extension;                                                        \
   if (MaybeNewExtension(number, &extension)) {                                 \
     extension->type = type;                                                    \
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_##UPPERCASE);\
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
     extension->is_repeated = true;                                             \
     extension->is_packed = packed;                                             \
     extension->repeated_##LOWERCASE##_value = new RepeatedField<LOWERCASE>();  \
@@ -290,7 +283,7 @@
   Extension* extension;
   if (MaybeNewExtension(number, &extension)) {
     extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_ENUM);
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
     extension->is_repeated = false;
   } else {
     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, ENUM);
@@ -318,7 +311,7 @@
   Extension* extension;
   if (MaybeNewExtension(number, &extension)) {
     extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_ENUM);
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
     extension->is_repeated = true;
     extension->is_packed = packed;
     extension->repeated_enum_value = new RepeatedField<int>();
@@ -348,7 +341,7 @@
   Extension* extension;
   if (MaybeNewExtension(number, &extension)) {
     extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_STRING);
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
     extension->is_repeated = false;
     extension->string_value = new string;
   } else {
@@ -376,7 +369,7 @@
   Extension* extension;
   if (MaybeNewExtension(number, &extension)) {
     extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_STRING);
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
     extension->is_repeated = true;
     extension->is_packed = false;
     extension->repeated_string_value = new RepeatedPtrField<string>();
@@ -389,8 +382,8 @@
 // -------------------------------------------------------------------
 // Messages
 
-const Message& ExtensionSet::GetMessage(int number,
-                                        const Message& default_value) const {
+const MessageLite& ExtensionSet::GetMessage(
+    int number, const MessageLite& default_value) const {
   map<int, Extension>::const_iterator iter = extensions_.find(number);
   if (iter == extensions_.end()) {
     // Not present.  Return the default value.
@@ -401,25 +394,17 @@
   }
 }
 
-const Message& ExtensionSet::GetMessage(int number,
-                                        const Descriptor* message_type,
-                                        MessageFactory* factory) const {
-  map<int, Extension>::const_iterator iter = extensions_.find(number);
-  if (iter == extensions_.end() || iter->second.is_cleared) {
-    // Not present.  Return the default value.
-    return *factory->GetPrototype(message_type);
-  } else {
-    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
-    return *iter->second.message_value;
-  }
-}
+// Defined in extension_set_heavy.cc.
+// const MessageLite& ExtensionSet::GetMessage(int number,
+//                                             const Descriptor* message_type,
+//                                             MessageFactory* factory) const
 
-Message* ExtensionSet::MutableMessage(int number, FieldType type,
-                                      const Message& prototype) {
+MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
+                                          const MessageLite& prototype) {
   Extension* extension;
   if (MaybeNewExtension(number, &extension)) {
     extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
     extension->is_repeated = false;
     extension->message_value = prototype.New();
   } else {
@@ -429,71 +414,54 @@
   return extension->message_value;
 }
 
-Message* ExtensionSet::MutableMessage(int number, FieldType type,
-                                      const Descriptor* message_type,
-                                      MessageFactory* factory) {
-  Extension* extension;
-  if (MaybeNewExtension(number, &extension)) {
-    extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
-    extension->is_repeated = false;
-    extension->is_packed = false;
-    const Message* prototype = factory->GetPrototype(message_type);
-    GOOGLE_CHECK(prototype != NULL);
-    extension->message_value = prototype->New();
-  } else {
-    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
-  }
-  extension->is_cleared = false;
-  return extension->message_value;
-}
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
+//                                           const Descriptor* message_type,
+//                                           MessageFactory* factory)
 
-const Message& ExtensionSet::GetRepeatedMessage(int number, int index) const {
+const MessageLite& ExtensionSet::GetRepeatedMessage(
+    int number, int index) const {
   map<int, Extension>::const_iterator iter = extensions_.find(number);
   GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
   GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE);
   return iter->second.repeated_message_value->Get(index);
 }
 
-Message* ExtensionSet::MutableRepeatedMessage(int number, int index) {
+MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) {
   map<int, Extension>::iterator iter = extensions_.find(number);
   GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
   GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE);
   return iter->second.repeated_message_value->Mutable(index);
 }
 
-Message* ExtensionSet::AddMessage(int number, FieldType type,
-                                  const Message& prototype) {
+MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
+                                      const MessageLite& prototype) {
   Extension* extension;
   if (MaybeNewExtension(number, &extension)) {
     extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
     extension->is_repeated = true;
     extension->repeated_message_value =
-      new RepeatedPtrField<Message>(&prototype);
+      new RepeatedPtrField<MessageLite>();
   } else {
     GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
   }
-  return extension->repeated_message_value->Add();
+
+  // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot
+  // allocate an abstract object, so we have to be tricky.
+  MessageLite* result = extension->repeated_message_value
+      ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
+  if (result == NULL) {
+    result = prototype.New();
+    extension->repeated_message_value->AddAllocated(result);
+  }
+  return result;
 }
 
-Message* ExtensionSet::AddMessage(int number, FieldType type,
-                                  const Descriptor* message_type,
-                                  MessageFactory* factory) {
-  Extension* extension;
-  if (MaybeNewExtension(number, &extension)) {
-    extension->type = type;
-    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
-    extension->is_repeated = true;
-    const Message* prototype = factory->GetPrototype(message_type);
-    GOOGLE_CHECK(prototype != NULL);
-    extension->repeated_message_value =
-      new RepeatedPtrField<Message>(prototype);
-  } else {
-    GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
-  }
-  return extension->repeated_message_value->Add();
-}
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
+//                                       const Descriptor* message_type,
+//                                       MessageFactory* factory)
 
 #undef GOOGLE_DCHECK_TYPE
 
@@ -505,35 +473,35 @@
   GOOGLE_DCHECK(extension->is_repeated);
 
   switch(cpp_type(extension->type)) {
-    case FieldDescriptor::CPPTYPE_INT32:   
-      extension->repeated_int32_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_INT32:
+      extension->repeated_int32_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_INT64:   
-      extension->repeated_int64_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_INT64:
+      extension->repeated_int64_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_UINT32:   
-      extension->repeated_uint32_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_UINT32:
+      extension->repeated_uint32_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_UINT64:   
-      extension->repeated_uint64_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_UINT64:
+      extension->repeated_uint64_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_FLOAT:   
-      extension->repeated_float_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_FLOAT:
+      extension->repeated_float_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_DOUBLE:   
-      extension->repeated_double_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_DOUBLE:
+      extension->repeated_double_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_BOOL:   
-      extension->repeated_bool_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_BOOL:
+      extension->repeated_bool_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_ENUM:   
-      extension->repeated_enum_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_ENUM:
+      extension->repeated_enum_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_STRING:   
-      extension->repeated_string_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_STRING:
+      extension->repeated_string_value->RemoveLast();
       break;
-    case FieldDescriptor::CPPTYPE_MESSAGE:   
-      extension->repeated_message_value->RemoveLast(); 
+    case WireFormatLite::CPPTYPE_MESSAGE:
+      extension->repeated_message_value->RemoveLast();
       break;
   }
 }
@@ -546,35 +514,35 @@
   GOOGLE_DCHECK(extension->is_repeated);
 
   switch(cpp_type(extension->type)) {
-    case FieldDescriptor::CPPTYPE_INT32:   
+    case WireFormatLite::CPPTYPE_INT32:
       extension->repeated_int32_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_INT64:   
-      extension->repeated_int64_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_INT64:
+      extension->repeated_int64_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_UINT32:   
+    case WireFormatLite::CPPTYPE_UINT32:
       extension->repeated_uint32_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_UINT64:   
+    case WireFormatLite::CPPTYPE_UINT64:
       extension->repeated_uint64_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_FLOAT:   
-      extension->repeated_float_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_FLOAT:
+      extension->repeated_float_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_DOUBLE:   
-      extension->repeated_double_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_DOUBLE:
+      extension->repeated_double_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_BOOL:   
-      extension->repeated_bool_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_BOOL:
+      extension->repeated_bool_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_ENUM:   
-      extension->repeated_enum_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_ENUM:
+      extension->repeated_enum_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_STRING:   
-      extension->repeated_string_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_STRING:
+      extension->repeated_string_value->SwapElements(index1, index2);
       break;
-    case FieldDescriptor::CPPTYPE_MESSAGE:   
-      extension->repeated_message_value->SwapElements(index1, index2); 
+    case WireFormatLite::CPPTYPE_MESSAGE:
+      extension->repeated_message_value->SwapElements(index1, index2);
       break;
   }
 }
@@ -607,7 +575,7 @@
 
       switch (cpp_type(other_extension.type)) {
 #define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE)             \
-        case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
+        case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
           if (is_new) {                                              \
             extension->repeated_##LOWERCASE##_value =                \
               new REPEATED_TYPE;                                     \
@@ -627,20 +595,32 @@
         HANDLE_TYPE( STRING,  string, RepeatedPtrField< string>);
 #undef HANDLE_TYPE
 
-        case FieldDescriptor::CPPTYPE_MESSAGE:
+        case WireFormatLite::CPPTYPE_MESSAGE:
           if (is_new) {
-            extension->repeated_message_value = new RepeatedPtrField<Message>(
-              other_extension.repeated_message_value->prototype());
+            extension->repeated_message_value =
+              new RepeatedPtrField<MessageLite>();
           }
-          extension->repeated_message_value->MergeFrom(
-            *other_extension.repeated_message_value);
+          // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
+          // it would attempt to allocate new objects.
+          RepeatedPtrField<MessageLite>* other_repeated_message =
+              other_extension.repeated_message_value;
+          for (int i = 0; i < other_repeated_message->size(); i++) {
+            const MessageLite& other_message = other_repeated_message->Get(i);
+            MessageLite* target = extension->repeated_message_value
+                     ->AddFromCleared<GenericTypeHandler<MessageLite> >();
+            if (target == NULL) {
+              target = other_message.New();
+              extension->repeated_message_value->AddAllocated(target);
+            }
+            target->CheckTypeAndMergeFrom(other_message);
+          }
           break;
       }
     } else {
       if (!other_extension.is_cleared) {
         switch (cpp_type(other_extension.type)) {
 #define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE)                         \
-          case FieldDescriptor::CPPTYPE_##UPPERCASE:                         \
+          case WireFormatLite::CPPTYPE_##UPPERCASE:                          \
             Set##CAMELCASE(iter->first, other_extension.type,                \
                            other_extension.LOWERCASE##_value);               \
             break;
@@ -654,14 +634,14 @@
           HANDLE_TYPE(  BOOL,   bool,   Bool);
           HANDLE_TYPE(  ENUM,   enum,   Enum);
 #undef HANDLE_TYPE
-          case FieldDescriptor::CPPTYPE_STRING:
+          case WireFormatLite::CPPTYPE_STRING:
             SetString(iter->first, other_extension.type,
                       *other_extension.string_value);
             break;
-          case FieldDescriptor::CPPTYPE_MESSAGE:
+          case WireFormatLite::CPPTYPE_MESSAGE:
             MutableMessage(iter->first, other_extension.type,
                            *other_extension.message_value)
-              ->MergeFrom(*other_extension.message_value);
+              ->CheckTypeAndMergeFrom(*other_extension.message_value);
             break;
         }
       }
@@ -679,7 +659,7 @@
   for (map<int, Extension>::const_iterator iter = extensions_.begin();
        iter != extensions_.end(); ++iter) {
     const Extension& extension = iter->second;
-    if (cpp_type(extension.type) == FieldDescriptor::CPPTYPE_MESSAGE) {
+    if (cpp_type(extension.type) == WireFormatLite::CPPTYPE_MESSAGE) {
       if (extension.is_repeated) {
         for (int i = 0; i < extension.repeated_message_value->size(); i++) {
           if (!extension.repeated_message_value->Get(i).IsInitialized()) {
@@ -698,10 +678,10 @@
 }
 
 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
-                              const Message* containing_type,
-                              UnknownFieldSet* unknown_fields) {
-  int number = WireFormat::GetTagFieldNumber(tag);
-  WireFormat::WireType wire_type = WireFormat::GetTagWireType(tag);
+                              const MessageLite* containing_type,
+                              FieldSkipper* field_skipper) {
+  int number = WireFormatLite::GetTagFieldNumber(tag);
+  WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
 
   const ExtensionInfo* extension =
       FindRegisteredExtension(containing_type, number);
@@ -710,15 +690,15 @@
   if (extension == NULL) {
     is_unknown = true;
   } else if (extension->is_packed) {
-    is_unknown = (wire_type != WireFormat::WIRETYPE_LENGTH_DELIMITED);
+    is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
   } else {
-    WireFormat::WireType expected_wire_type =
-        WireFormat::WireTypeForFieldType(real_type(extension->type));
+    WireFormatLite::WireType expected_wire_type =
+        WireFormatLite::WireTypeForFieldType(real_type(extension->type));
     is_unknown = (wire_type != expected_wire_type);
   }
 
   if (is_unknown) {
-    WireFormat::SkipField(input, tag, unknown_fields);
+    field_skipper->SkipField(input, tag);
   } else if (extension->is_packed) {
     uint32 size;
     if (!input->ReadVarint32(&size)) return false;
@@ -726,11 +706,11 @@
 
     switch (extension->type) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE)        \
-      case FieldDescriptor::TYPE_##UPPERCASE:                                  \
+      case WireFormatLite::TYPE_##UPPERCASE:                                   \
         while (input->BytesUntilLimit() > 0) {                                 \
           CPP_LOWERCASE value;                                                 \
-          if (!WireFormat::Read##CAMELCASE(input, &value)) return false;       \
-          Add##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE,        \
+          if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false;   \
+          Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,         \
                              true, value);                                     \
         }                                                                      \
         break
@@ -750,20 +730,20 @@
       HANDLE_TYPE(    BOOL,     Bool,    Bool,    bool);
 #undef HANDLE_TYPE
 
-      case FieldDescriptor::TYPE_ENUM:
+      case WireFormatLite::TYPE_ENUM:
         while (input->BytesUntilLimit() > 0) {
           int value;
-          if (!WireFormat::ReadEnum(input, &value)) return false;
+          if (!WireFormatLite::ReadEnum(input, &value)) return false;
           if (extension->enum_is_valid(value)) {
-            AddEnum(number, FieldDescriptor::TYPE_ENUM, true, value);
+            AddEnum(number, WireFormatLite::TYPE_ENUM, true, value);
           }
         }
         break;
 
-      case FieldDescriptor::TYPE_STRING:
-      case FieldDescriptor::TYPE_BYTES:
-      case FieldDescriptor::TYPE_GROUP:
-      case FieldDescriptor::TYPE_MESSAGE:
+      case WireFormatLite::TYPE_STRING:
+      case WireFormatLite::TYPE_BYTES:
+      case WireFormatLite::TYPE_GROUP:
+      case WireFormatLite::TYPE_MESSAGE:
         GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
         break;
     }
@@ -772,14 +752,14 @@
   } else {
     switch (extension->type) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE)        \
-      case FieldDescriptor::TYPE_##UPPERCASE: {                                \
+      case WireFormatLite::TYPE_##UPPERCASE: {                                 \
         CPP_LOWERCASE value;                                                   \
-        if (!WireFormat::Read##CAMELCASE(input, &value)) return false;         \
+        if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false;     \
         if (extension->is_repeated) {                                          \
-          Add##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE,        \
+          Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,         \
                              false, value);                                    \
         } else {                                                               \
-          Set##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, value);\
+          Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value); \
         }                                                                      \
       } break
 
@@ -798,56 +778,54 @@
       HANDLE_TYPE(    BOOL,     Bool,    Bool,    bool);
 #undef HANDLE_TYPE
 
-      case FieldDescriptor::TYPE_ENUM: {
+      case WireFormatLite::TYPE_ENUM: {
         int value;
-        if (!WireFormat::ReadEnum(input, &value)) return false;
+        if (!WireFormatLite::ReadEnum(input, &value)) return false;
 
         if (!extension->enum_is_valid(value)) {
           // Invalid value.  Treat as unknown.
-          if (unknown_fields != NULL) {
-            unknown_fields->AddVarint(number, value);
-          }
+          field_skipper->SkipUnknownEnum(number, value);
         } else if (extension->is_repeated) {
-          AddEnum(number, FieldDescriptor::TYPE_ENUM, false, value);
+          AddEnum(number, WireFormatLite::TYPE_ENUM, false, value);
         } else {
-          SetEnum(number, FieldDescriptor::TYPE_ENUM, value);
+          SetEnum(number, WireFormatLite::TYPE_ENUM, value);
         }
         break;
       }
 
-      case FieldDescriptor::TYPE_STRING:  {
+      case WireFormatLite::TYPE_STRING:  {
         string* value = extension->is_repeated ?
-          AddString(number, FieldDescriptor::TYPE_STRING) :
-          MutableString(number, FieldDescriptor::TYPE_STRING);
-        if (!WireFormat::ReadString(input, value)) return false;
+          AddString(number, WireFormatLite::TYPE_STRING) :
+          MutableString(number, WireFormatLite::TYPE_STRING);
+        if (!WireFormatLite::ReadString(input, value)) return false;
         break;
       }
 
-      case FieldDescriptor::TYPE_BYTES:  {
+      case WireFormatLite::TYPE_BYTES:  {
         string* value = extension->is_repeated ?
-          AddString(number, FieldDescriptor::TYPE_STRING) :
-          MutableString(number, FieldDescriptor::TYPE_STRING);
-        if (!WireFormat::ReadBytes(input, value)) return false;
+          AddString(number, WireFormatLite::TYPE_STRING) :
+          MutableString(number, WireFormatLite::TYPE_STRING);
+        if (!WireFormatLite::ReadBytes(input, value)) return false;
         break;
       }
 
-      case FieldDescriptor::TYPE_GROUP: {
-        Message* value = extension->is_repeated ?
-            AddMessage(number, FieldDescriptor::TYPE_GROUP,
+      case WireFormatLite::TYPE_GROUP: {
+        MessageLite* value = extension->is_repeated ?
+            AddMessage(number, WireFormatLite::TYPE_GROUP,
                        *extension->message_prototype) :
-            MutableMessage(number, FieldDescriptor::TYPE_GROUP,
+            MutableMessage(number, WireFormatLite::TYPE_GROUP,
                            *extension->message_prototype);
-        if (!WireFormat::ReadGroup(number, input, value)) return false;
+        if (!WireFormatLite::ReadGroup(number, input, value)) return false;
         break;
       }
 
-      case FieldDescriptor::TYPE_MESSAGE: {
-        Message* value = extension->is_repeated ?
-            AddMessage(number, FieldDescriptor::TYPE_MESSAGE,
+      case WireFormatLite::TYPE_MESSAGE: {
+        MessageLite* value = extension->is_repeated ?
+            AddMessage(number, WireFormatLite::TYPE_MESSAGE,
                        *extension->message_prototype) :
-            MutableMessage(number, FieldDescriptor::TYPE_MESSAGE,
+            MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
                            *extension->message_prototype);
-        if (!WireFormat::ReadMessage(input, value)) return false;
+        if (!WireFormatLite::ReadMessage(input, value)) return false;
         break;
       }
     }
@@ -856,6 +834,130 @@
   return true;
 }
 
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              const MessageLite* containing_type) {
+  FieldSkipper skipper;
+  return ParseField(tag, input, containing_type, &skipper);
+}
+
+// Defined in extension_set_heavy.cc.
+// bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+//                               const MessageLite* containing_type,
+//                               UnknownFieldSet* unknown_fields)
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   const MessageLite* containing_type,
+                                   FieldSkipper* field_skipper) {
+  while (true) {
+    uint32 tag = input->ReadTag();
+    switch (tag) {
+      case 0:
+        return true;
+      case WireFormatLite::kMessageSetItemStartTag:
+        if (!ParseMessageSetItem(input, containing_type, field_skipper)) {
+          return false;
+        }
+        break;
+      default:
+        if (!ParseField(tag, input, containing_type, field_skipper)) {
+          return false;
+        }
+        break;
+    }
+  }
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   const MessageLite* containing_type) {
+  FieldSkipper skipper;
+  return ParseMessageSet(input, containing_type, &skipper);
+}
+
+// Defined in extension_set_heavy.cc.
+// bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+//                                    const MessageLite* containing_type,
+//                                    UnknownFieldSet* unknown_fields);
+
+bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
+                                       const MessageLite* containing_type,
+                                       FieldSkipper* field_skipper) {
+  // TODO(kenton):  It would be nice to share code between this and
+  // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
+  // differences would be hard to factor out.
+
+  // This method parses a group which should contain two fields:
+  //   required int32 type_id = 2;
+  //   required data message = 3;
+
+  // Once we see a type_id, we'll construct a fake tag for this extension
+  // which is the tag it would have had under the proto2 extensions wire
+  // format.
+  uint32 fake_tag = 0;
+
+  // If we see message data before the type_id, we'll append it to this so
+  // we can parse it later.  This will probably never happen in practice,
+  // as no MessageSet encoder I know of writes the message before the type ID.
+  // But, it's technically valid so we should allow it.
+  // TODO(kenton):  Use a Cord instead?  Do I care?
+  string message_data;
+
+  while (true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) return false;
+
+    switch (tag) {
+      case WireFormatLite::kMessageSetTypeIdTag: {
+        uint32 type_id;
+        if (!input->ReadVarint32(&type_id)) return false;
+        fake_tag = WireFormatLite::MakeTag(type_id,
+            WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+        if (!message_data.empty()) {
+          // We saw some message data before the type_id.  Have to parse it
+          // now.
+          io::CodedInputStream sub_input(
+              reinterpret_cast<const uint8*>(message_data.data()),
+              message_data.size());
+          if (!ParseField(fake_tag, &sub_input,
+                          containing_type, field_skipper)) {
+            return false;
+          }
+          message_data.clear();
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetMessageTag: {
+        if (fake_tag == 0) {
+          // We haven't seen a type_id yet.  Append this data to message_data.
+          string temp;
+          uint32 length;
+          if (!input->ReadVarint32(&length)) return false;
+          if (!input->ReadString(&temp, length)) return false;
+          message_data.append(temp);
+        } else {
+          // Already saw type_id, so we can parse this directly.
+          if (!ParseField(fake_tag, input,
+                          containing_type, field_skipper)) {
+            return false;
+          }
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetItemEndTag: {
+        return true;
+      }
+
+      default: {
+        if (!field_skipper->SkipField(input, tag)) return false;
+      }
+    }
+  }
+}
+
 void ExtensionSet::SerializeWithCachedSizes(
     int start_field_number, int end_field_number,
     io::CodedOutputStream* output) const {
@@ -887,6 +989,31 @@
   return target + written_bytes;
 }
 
+void ExtensionSet::SerializeMessageSetWithCachedSizes(
+    io::CodedOutputStream* output) const {
+  map<int, Extension>::const_iterator iter;
+  for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+    iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
+  }
+}
+
+uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
+    uint8* target) const {
+  // For now, just create an array output stream around the target and dispatch
+  // to SerializeWithCachedSizes(). Give the array output stream kint32max
+  // bytes; we will certainly write less than that. It is up to the caller to
+  // ensure that the buffer has sufficient space.
+  int written_bytes;
+  {
+    io::ArrayOutputStream array_stream(target, kint32max);
+    io::CodedOutputStream output_stream(&array_stream);
+    SerializeMessageSetWithCachedSizes(&output_stream);
+    written_bytes = output_stream.ByteCount();
+    GOOGLE_DCHECK(!output_stream.HadError());
+  }
+  return target + written_bytes;
+}
+
 int ExtensionSet::ByteSize() const {
   int total_size = 0;
 
@@ -898,18 +1025,20 @@
   return total_size;
 }
 
-int ExtensionSet::SpaceUsedExcludingSelf() const {
-  int total_size =
-      extensions_.size() * sizeof(map<int, Extension>::value_type);
-  for (map<int, Extension>::const_iterator iter = extensions_.begin(),
-       end = extensions_.end();
-       iter != end;
-       ++iter) {
-    total_size += iter->second.SpaceUsedExcludingSelf();
+int ExtensionSet::MessageSetByteSize() const {
+  int total_size = 0;
+
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    total_size += iter->second.MessageSetItemByteSize(iter->first);
   }
+
   return total_size;
 }
 
+// Defined in extension_set_heavy.cc.
+// int ExtensionSet::SpaceUsedExcludingSelf() const
+
 bool ExtensionSet::MaybeNewExtension(int number, Extension** result) {
   pair<map<int, Extension>::iterator, bool> insert_result =
       extensions_.insert(make_pair(number, Extension()));
@@ -924,7 +1053,7 @@
   if (is_repeated) {
     switch (cpp_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
-      case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
+      case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
         repeated_##LOWERCASE##_value->Clear();                     \
         break
 
@@ -943,10 +1072,10 @@
   } else {
     if (!is_cleared) {
       switch (cpp_type(type)) {
-        case FieldDescriptor::CPPTYPE_STRING:
+        case WireFormatLite::CPPTYPE_STRING:
           string_value->clear();
           break;
-        case FieldDescriptor::CPPTYPE_MESSAGE:
+        case WireFormatLite::CPPTYPE_MESSAGE:
           message_value->Clear();
           break;
         default:
@@ -968,15 +1097,15 @@
     if (is_packed) {
       if (cached_size == 0) return;
 
-      WireFormat::WriteTag(number, WireFormat::WIRETYPE_LENGTH_DELIMITED,
-                           output);
+      WireFormatLite::WriteTag(number,
+          WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
       output->WriteVarint32(cached_size);
 
       switch (real_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
           for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
-            WireFormat::Write##CAMELCASE##NoTag(                            \
+            WireFormatLite::Write##CAMELCASE##NoTag(                        \
               repeated_##LOWERCASE##_value->Get(i), output);                \
           }                                                                 \
           break
@@ -997,19 +1126,19 @@
         HANDLE_TYPE(    ENUM,     Enum,    enum);
 #undef HANDLE_TYPE
 
-        case FieldDescriptor::TYPE_STRING:
-        case FieldDescriptor::TYPE_BYTES:
-        case FieldDescriptor::TYPE_GROUP:
-        case FieldDescriptor::TYPE_MESSAGE:
+        case WireFormatLite::TYPE_STRING:
+        case WireFormatLite::TYPE_BYTES:
+        case WireFormatLite::TYPE_GROUP:
+        case WireFormatLite::TYPE_MESSAGE:
           GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
           break;
       }
     } else {
       switch (real_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
           for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
-            WireFormat::Write##CAMELCASE(number,                            \
+            WireFormatLite::Write##CAMELCASE(number,                        \
               repeated_##LOWERCASE##_value->Get(i), output);                \
           }                                                                 \
           break
@@ -1038,8 +1167,8 @@
   } else if (!is_cleared) {
     switch (real_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE)                 \
-      case FieldDescriptor::TYPE_##UPPERCASE:                    \
-        WireFormat::Write##CAMELCASE(number, VALUE, output);     \
+      case WireFormatLite::TYPE_##UPPERCASE:                     \
+        WireFormatLite::Write##CAMELCASE(number, VALUE, output); \
         break
 
       HANDLE_TYPE(   INT32,    Int32,    int32_value);
@@ -1065,6 +1194,34 @@
   }
 }
 
+void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
+    int number,
+    io::CodedOutputStream* output) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but serialize it the normal way.
+    SerializeFieldWithCachedSizes(number, output);
+    return;
+  }
+
+  if (is_cleared) return;
+
+  // Start group.
+  output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
+
+  // Write type ID.
+  output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
+  output->WriteVarint32(number);
+
+  // Write message.
+  output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
+
+  output->WriteVarint32(message_value->GetCachedSize());
+  message_value->SerializeWithCachedSizes(output);
+
+  // End group.
+  output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
+}
+
 int ExtensionSet::Extension::ByteSize(int number) const {
   int result = 0;
 
@@ -1072,9 +1229,9 @@
     if (is_packed) {
       switch (real_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
           for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
-            result += WireFormat::CAMELCASE##Size(                          \
+            result += WireFormatLite::CAMELCASE##Size(                      \
               repeated_##LOWERCASE##_value->Get(i));                        \
           }                                                                 \
           break
@@ -1090,8 +1247,8 @@
 
         // Stuff with fixed size.
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
-          result += WireFormat::k##CAMELCASE##Size *                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          result += WireFormatLite::k##CAMELCASE##Size *                    \
                     repeated_##LOWERCASE##_value->size();                   \
           break
         HANDLE_TYPE( FIXED32,  Fixed32, uint32);
@@ -1103,10 +1260,10 @@
         HANDLE_TYPE(    BOOL,     Bool,   bool);
 #undef HANDLE_TYPE
 
-        case FieldDescriptor::TYPE_STRING:
-        case FieldDescriptor::TYPE_BYTES:
-        case FieldDescriptor::TYPE_GROUP:
-        case FieldDescriptor::TYPE_MESSAGE:
+        case WireFormatLite::TYPE_STRING:
+        case WireFormatLite::TYPE_BYTES:
+        case WireFormatLite::TYPE_GROUP:
+        case WireFormatLite::TYPE_MESSAGE:
           GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
           break;
       }
@@ -1115,17 +1272,18 @@
       if (result > 0) {
         result += io::CodedOutputStream::VarintSize32(result);
         result += io::CodedOutputStream::VarintSize32(
-            WireFormat::MakeTag(number, WireFormat::WIRETYPE_LENGTH_DELIMITED));
+            WireFormatLite::MakeTag(number,
+                WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
       }
     } else {
-      int tag_size = WireFormat::TagSize(number, real_type(type));
+      int tag_size = WireFormatLite::TagSize(number, real_type(type));
 
       switch (real_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
           result += tag_size * repeated_##LOWERCASE##_value->size();        \
           for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
-            result += WireFormat::CAMELCASE##Size(                          \
+            result += WireFormatLite::CAMELCASE##Size(                      \
               repeated_##LOWERCASE##_value->Get(i));                        \
           }                                                                 \
           break
@@ -1145,8 +1303,8 @@
 
         // Stuff with fixed size.
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
-          result += (tag_size + WireFormat::k##CAMELCASE##Size) *           \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          result += (tag_size + WireFormatLite::k##CAMELCASE##Size) *       \
                     repeated_##LOWERCASE##_value->size();                   \
           break
         HANDLE_TYPE( FIXED32,  Fixed32, uint32);
@@ -1160,11 +1318,11 @@
       }
     }
   } else if (!is_cleared) {
-    result += WireFormat::TagSize(number, real_type(type));
+    result += WireFormatLite::TagSize(number, real_type(type));
     switch (real_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                      \
-      case FieldDescriptor::TYPE_##UPPERCASE:                             \
-        result += WireFormat::CAMELCASE##Size(LOWERCASE);                 \
+      case WireFormatLite::TYPE_##UPPERCASE:                              \
+        result += WireFormatLite::CAMELCASE##Size(LOWERCASE);             \
         break
 
       HANDLE_TYPE(   INT32,    Int32,    int32_value);
@@ -1182,8 +1340,8 @@
 
       // Stuff with fixed size.
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE)                                 \
-      case FieldDescriptor::TYPE_##UPPERCASE:                             \
-        result += WireFormat::k##CAMELCASE##Size;                         \
+      case WireFormatLite::TYPE_##UPPERCASE:                              \
+        result += WireFormatLite::k##CAMELCASE##Size;                     \
         break
       HANDLE_TYPE( FIXED32,  Fixed32);
       HANDLE_TYPE( FIXED64,  Fixed64);
@@ -1199,11 +1357,34 @@
   return result;
 }
 
+int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but compute the byte size for it the
+    // normal way.
+    return ByteSize(number);
+  }
+
+  if (is_cleared) return 0;
+
+  int our_size = WireFormatLite::kMessageSetItemTagsSize;
+
+  // type_id
+  our_size += io::CodedOutputStream::VarintSize32(number);
+
+  // message
+  int message_size = message_value->ByteSize();
+
+  our_size += io::CodedOutputStream::VarintSize32(message_size);
+  our_size += message_size;
+
+  return our_size;
+}
+
 int ExtensionSet::Extension::GetSize() const {
   GOOGLE_DCHECK(is_repeated);
   switch (cpp_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                        \
-    case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
+    case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
       return repeated_##LOWERCASE##_value->size()
 
     HANDLE_TYPE(  INT32,   int32);
@@ -1227,7 +1408,7 @@
   if (is_repeated) {
     switch (cpp_type(type)) {
 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
-      case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
+      case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
         delete repeated_##LOWERCASE##_value;                       \
         break
 
@@ -1245,10 +1426,10 @@
     }
   } else {
     switch (cpp_type(type)) {
-      case FieldDescriptor::CPPTYPE_STRING:
+      case WireFormatLite::CPPTYPE_STRING:
         delete string_value;
         break;
-      case FieldDescriptor::CPPTYPE_MESSAGE:
+      case WireFormatLite::CPPTYPE_MESSAGE:
         delete message_value;
         break;
       default:
@@ -1257,43 +1438,8 @@
   }
 }
 
-int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
-  int total_size = 0;
-  if (is_repeated) {
-    switch (cpp_type(type)) {
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
-      case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
-        total_size += sizeof(*repeated_##LOWERCASE##_value) +      \
-            repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
-        break
-
-      HANDLE_TYPE(  INT32,   int32);
-      HANDLE_TYPE(  INT64,   int64);
-      HANDLE_TYPE( UINT32,  uint32);
-      HANDLE_TYPE( UINT64,  uint64);
-      HANDLE_TYPE(  FLOAT,   float);
-      HANDLE_TYPE( DOUBLE,  double);
-      HANDLE_TYPE(   BOOL,    bool);
-      HANDLE_TYPE(   ENUM,    enum);
-      HANDLE_TYPE( STRING,  string);
-      HANDLE_TYPE(MESSAGE, message);
-    }
-  } else {
-    switch (cpp_type(type)) {
-      case FieldDescriptor::CPPTYPE_STRING:
-        total_size += sizeof(*string_value) +
-                      StringSpaceUsedExcludingSelf(*string_value);
-        break;
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        total_size += message_value->SpaceUsed();
-        break;
-      default:
-        // No extra storage costs for primitive types.
-        break;
-    }
-  }
-  return total_size;
-}
+// Defined in extension_set_heavy.cc.
+// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index e04614c..8c1d73b 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -45,20 +45,23 @@
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/message.h>
 
 namespace google {
+
 namespace protobuf {
   class Descriptor;                                    // descriptor.h
   class FieldDescriptor;                               // descriptor.h
   class DescriptorPool;                                // descriptor.h
-  class Message;                                       // message.h
+  class MessageLite;                                   // message_lite.h
   class MessageFactory;                                // message.h
   class UnknownFieldSet;                               // unknown_field_set.h
   namespace io {
     class CodedInputStream;                              // coded_stream.h
     class CodedOutputStream;                             // coded_stream.h
   }
+  namespace internal {
+    class FieldSkipper;                                  // wire_format_lite.h
+  }
   template <typename Element> class RepeatedField;     // repeated_field.h
   template <typename Element> class RepeatedPtrField;  // repeated_field.h
 }
@@ -66,9 +69,9 @@
 namespace protobuf {
 namespace internal {
 
-// Used to store values of type FieldDescriptor::Type without having to
-// #include descriptor.h.  Also, ensures that we use only one byte to store
-// these values, which is important to keep the layout of
+// Used to store values of type WireFormatLite::FieldType without having to
+// #include wire_format_lite.h.  Also, ensures that we use only one byte to
+// store these values, which is important to keep the layout of
 // ExtensionSet::Extension small.
 typedef uint8 FieldType;
 
@@ -98,17 +101,17 @@
   // to look up extensions for parsed field numbers.  Note that dynamic parsing
   // does not use ParseField(); only protocol-compiler-generated parsing
   // methods do.
-  static void RegisterExtension(const Message* containing_type,
+  static void RegisterExtension(const MessageLite* containing_type,
                                 int number, FieldType type,
                                 bool is_repeated, bool is_packed);
-  static void RegisterEnumExtension(const Message* containing_type,
+  static void RegisterEnumExtension(const MessageLite* containing_type,
                                     int number, FieldType type,
                                     bool is_repeated, bool is_packed,
                                     EnumValidityFunc* is_valid);
-  static void RegisterMessageExtension(const Message* containing_type,
+  static void RegisterMessageExtension(const MessageLite* containing_type,
                                        int number, FieldType type,
                                        bool is_repeated, bool is_packed,
-                                       const Message* prototype);
+                                       const MessageLite* prototype);
 
   // =================================================================
 
@@ -167,9 +170,10 @@
   bool   GetBool  (int number, bool   default_value) const;
   int    GetEnum  (int number, int    default_value) const;
   const string & GetString (int number, const string&  default_value) const;
-  const Message& GetMessage(int number, const Message& default_value) const;
-  const Message& GetMessage(int number, const Descriptor* message_type,
-                            MessageFactory* factory) const;
+  const MessageLite& GetMessage(int number,
+                                const MessageLite& default_value) const;
+  const MessageLite& GetMessage(int number, const Descriptor* message_type,
+                                MessageFactory* factory) const;
 
   void SetInt32 (int number, FieldType type, int32  value);
   void SetInt64 (int number, FieldType type, int64  value);
@@ -181,11 +185,11 @@
   void SetEnum  (int number, FieldType type, int    value);
   void SetString(int number, FieldType type, const string& value);
   string * MutableString (int number, FieldType type);
-  Message* MutableMessage(int number, FieldType type,
-                          const Message& prototype);
-  Message* MutableMessage(int number, FieldType type,
-                          const Descriptor* message_type,
-                          MessageFactory* factory);
+  MessageLite* MutableMessage(int number, FieldType type,
+                              const MessageLite& prototype);
+  MessageLite* MutableMessage(int number, FieldType type,
+                              const Descriptor* message_type,
+                              MessageFactory* factory);
 
   // repeated fields -------------------------------------------------
 
@@ -198,7 +202,7 @@
   bool   GetRepeatedBool  (int number, int index) const;
   int    GetRepeatedEnum  (int number, int index) const;
   const string & GetRepeatedString (int number, int index) const;
-  const Message& GetRepeatedMessage(int number, int index) const;
+  const MessageLite& GetRepeatedMessage(int number, int index) const;
 
   void SetRepeatedInt32 (int number, int index, int32  value);
   void SetRepeatedInt64 (int number, int index, int64  value);
@@ -210,7 +214,7 @@
   void SetRepeatedEnum  (int number, int index, int    value);
   void SetRepeatedString(int number, int index, const string& value);
   string * MutableRepeatedString (int number, int index);
-  Message* MutableRepeatedMessage(int number, int index);
+  MessageLite* MutableRepeatedMessage(int number, int index);
 
   void AddInt32 (int number, FieldType type, bool packed, int32  value);
   void AddInt64 (int number, FieldType type, bool packed, int64  value);
@@ -222,11 +226,11 @@
   void AddEnum  (int number, FieldType type, bool packed, int    value);
   void AddString(int number, FieldType type, const string& value);
   string * AddString (int number, FieldType type);
-  Message* AddMessage(int number, FieldType type,
-                      const Message& prototype);
-  Message* AddMessage(int number, FieldType type,
-                      const Descriptor* message_type,
-                      MessageFactory* factory);
+  MessageLite* AddMessage(int number, FieldType type,
+                          const MessageLite& prototype);
+  MessageLite* AddMessage(int number, FieldType type,
+                          const Descriptor* message_type,
+                          MessageFactory* factory);
 
   void RemoveLast(int number);
   void SwapElements(int number, int index1, int index2);
@@ -252,9 +256,31 @@
   // methods of ExtensionSet, this only works for generated message types --
   // it looks up extensions registered using RegisterExtension().
   bool ParseField(uint32 tag, io::CodedInputStream* input,
-                  const Message* containing_type,
+                  const MessageLite* containing_type,
+                  FieldSkipper* field_skipper);
+
+  // Specific versions for lite or full messages (constructs the appropriate
+  // FieldSkipper automatically).
+  bool ParseField(uint32 tag, io::CodedInputStream* input,
+                  const MessageLite* containing_type);
+  bool ParseField(uint32 tag, io::CodedInputStream* input,
+                  const MessageLite* containing_type,
                   UnknownFieldSet* unknown_fields);
 
+  // Parse an entire message in MessageSet format.  Such messages have no
+  // fields, only extensions.
+  bool ParseMessageSet(io::CodedInputStream* input,
+                       const MessageLite* containing_type,
+                       FieldSkipper* field_skipper);
+
+  // Specific versions for lite or full messages (constructs the appropriate
+  // FieldSkipper automatically).
+  bool ParseMessageSet(io::CodedInputStream* input,
+                       const MessageLite* containing_type);
+  bool ParseMessageSet(io::CodedInputStream* input,
+                       const MessageLite* containing_type,
+                       UnknownFieldSet* unknown_fields);
+
   // Write all extension fields with field numbers in the range
   //   [start_field_number, end_field_number)
   // to the output stream, using the cached sizes computed when ByteSize() was
@@ -272,37 +298,50 @@
                                          int end_field_number,
                                          uint8* target) const;
 
+  // Like above but serializes in MessageSet format.
+  void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
+  uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const;
+
   // Returns the total serialized size of all the extensions.
   int ByteSize() const;
 
+  // Like ByteSize() but uses MessageSet format.
+  int MessageSetByteSize() const;
+
   // Returns (an estimate of) the total number of bytes used for storing the
-  // extensions in memory, excluding sizeof(*this).
+  // extensions in memory, excluding sizeof(*this).  If the ExtensionSet is
+  // for a lite message (and thus possibly contains lite messages), the results
+  // are undefined (might work, might crash, might corrupt data, might not even
+  // be linked in).  It's up to the protocol compiler to avoid calling this on
+  // such ExtensionSets (easy enough since lite messages don't implement
+  // SpaceUsed()).
   int SpaceUsedExcludingSelf() const;
 
  private:
+
   struct Extension {
     union {
-      int32    int32_value;
-      int64    int64_value;
-      uint32   uint32_value;
-      uint64   uint64_value;
-      float    float_value;
-      double   double_value;
-      bool     bool_value;
-      int      enum_value;
-      string*  string_value;
-      Message* message_value;
+      int32        int32_value;
+      int64        int64_value;
+      uint32       uint32_value;
+      uint64       uint64_value;
+      float        float_value;
+      double       double_value;
+      bool         bool_value;
+      int          enum_value;
+      string*      string_value;
+      MessageLite* message_value;
 
-      RepeatedField   <int32  >* repeated_int32_value;
-      RepeatedField   <int64  >* repeated_int64_value;
-      RepeatedField   <uint32 >* repeated_uint32_value;
-      RepeatedField   <uint64 >* repeated_uint64_value;
-      RepeatedField   <float  >* repeated_float_value;
-      RepeatedField   <double >* repeated_double_value;
-      RepeatedField   <bool   >* repeated_bool_value;
-      RepeatedField   <int    >* repeated_enum_value;
-      RepeatedPtrField<string >* repeated_string_value;
-      RepeatedPtrField<Message>* repeated_message_value;
+      RepeatedField   <int32      >* repeated_int32_value;
+      RepeatedField   <int64      >* repeated_int64_value;
+      RepeatedField   <uint32     >* repeated_uint32_value;
+      RepeatedField   <uint64     >* repeated_uint64_value;
+      RepeatedField   <float      >* repeated_float_value;
+      RepeatedField   <double     >* repeated_double_value;
+      RepeatedField   <bool       >* repeated_bool_value;
+      RepeatedField   <int        >* repeated_enum_value;
+      RepeatedPtrField<string     >* repeated_string_value;
+      RepeatedPtrField<MessageLite>* repeated_message_value;
     };
 
     FieldType type;
@@ -328,7 +367,11 @@
     void SerializeFieldWithCachedSizes(
         int number,
         io::CodedOutputStream* output) const;
+    void SerializeMessageSetItemWithCachedSizes(
+        int number,
+        io::CodedOutputStream* output) const;
     int ByteSize(int number) const;
+    int MessageSetItemByteSize(int number) const;
     void Clear();
     int GetSize() const;
     void Free();
@@ -339,6 +382,13 @@
   // already exist.  Returns true if the extension did not already exist.
   bool MaybeNewExtension(int number, Extension** result);
 
+  // Parse a single MessageSet item -- called just after the item group start
+  // tag has been read.
+  bool ParseMessageSetItem(io::CodedInputStream* input,
+                           const MessageLite* containing_type,
+                           FieldSkipper* field_skipper);
+
+
   // The Extension struct is small enough to be passed by value, so we use it
   // directly as the value type in the map rather than use pointers.  We use
   // a map rather than hash_map here because we expect most ExtensionSets will
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
new file mode 100644
index 0000000..dbe9e33
--- /dev/null
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -0,0 +1,218 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Contains methods defined in extension_set.h which cannot be part of the
+// lite library because they use descriptors or reflection.
+
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+void ExtensionSet::AppendToList(const Descriptor* containing_type,
+                                const DescriptorPool* pool,
+                                vector<const FieldDescriptor*>* output) const {
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    bool has = false;
+    if (iter->second.is_repeated) {
+      has = iter->second.GetSize() > 0;
+    } else {
+      has = !iter->second.is_cleared;
+    }
+
+    if (has) {
+      output->push_back(
+          pool->FindExtensionByNumber(containing_type, iter->first));
+    }
+  }
+}
+
+inline FieldDescriptor::CppType cpp_type(FieldType type) {
+  return FieldDescriptor::TypeToCppType(
+      static_cast<FieldDescriptor::Type>(type));
+}
+
+#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                            \
+  GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED     \
+                                  : FieldDescriptor::LABEL_OPTIONAL,      \
+            FieldDescriptor::LABEL_##LABEL);                              \
+  GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
+
+const MessageLite& ExtensionSet::GetMessage(int number,
+                                            const Descriptor* message_type,
+                                            MessageFactory* factory) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end() || iter->second.is_cleared) {
+    // Not present.  Return the default value.
+    return *factory->GetPrototype(message_type);
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    return *iter->second.message_value;
+  }
+}
+
+MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
+                                          const Descriptor* message_type,
+                                          MessageFactory* factory) {
+  Extension* extension;
+  if (MaybeNewExtension(number, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+    extension->is_repeated = false;
+    extension->is_packed = false;
+    const MessageLite* prototype = factory->GetPrototype(message_type);
+    GOOGLE_CHECK(prototype != NULL);
+    extension->message_value = prototype->New();
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+  }
+  extension->is_cleared = false;
+  return extension->message_value;
+}
+
+MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
+                                      const Descriptor* message_type,
+                                      MessageFactory* factory) {
+  Extension* extension;
+  if (MaybeNewExtension(number, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+    extension->is_repeated = true;
+    extension->repeated_message_value =
+      new RepeatedPtrField<MessageLite>();
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
+  }
+
+  // RepeatedPtrField<Message> does not know how to Add() since it cannot
+  // allocate an abstract object, so we have to be tricky.
+  MessageLite* result = extension->repeated_message_value
+      ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
+  if (result == NULL) {
+    const MessageLite* prototype;
+    if (extension->repeated_message_value->size() == 0) {
+      prototype = factory->GetPrototype(message_type);
+      GOOGLE_CHECK(prototype != NULL);
+    } else {
+      prototype = &extension->repeated_message_value->Get(0);
+    }
+    result = prototype->New();
+    extension->repeated_message_value->AddAllocated(result);
+  }
+  return result;
+}
+
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              const MessageLite* containing_type,
+                              UnknownFieldSet* unknown_fields) {
+  UnknownFieldSetFieldSkipper skipper(unknown_fields);
+  return ParseField(tag, input, containing_type, &skipper);
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   const MessageLite* containing_type,
+                                   UnknownFieldSet* unknown_fields) {
+  UnknownFieldSetFieldSkipper skipper(unknown_fields);
+  return ParseMessageSet(input, containing_type, &skipper);
+}
+
+int ExtensionSet::SpaceUsedExcludingSelf() const {
+  int total_size =
+      extensions_.size() * sizeof(map<int, Extension>::value_type);
+  for (map<int, Extension>::const_iterator iter = extensions_.begin(),
+       end = extensions_.end();
+       iter != end;
+       ++iter) {
+    total_size += iter->second.SpaceUsedExcludingSelf();
+  }
+  return total_size;
+}
+
+int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
+  int total_size = 0;
+  if (is_repeated) {
+    switch (cpp_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
+      case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
+        total_size += sizeof(*repeated_##LOWERCASE##_value) +      \
+            repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
+        break
+
+      HANDLE_TYPE(  INT32,   int32);
+      HANDLE_TYPE(  INT64,   int64);
+      HANDLE_TYPE( UINT32,  uint32);
+      HANDLE_TYPE( UINT64,  uint64);
+      HANDLE_TYPE(  FLOAT,   float);
+      HANDLE_TYPE( DOUBLE,  double);
+      HANDLE_TYPE(   BOOL,    bool);
+      HANDLE_TYPE(   ENUM,    enum);
+      HANDLE_TYPE( STRING,  string);
+
+      case WireFormatLite::CPPTYPE_MESSAGE:
+        // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
+        // but MessageLite has no SpaceUsed(), so we must directly call
+        // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
+        // handler.
+        total_size += sizeof(*repeated_message_value) +
+            repeated_message_value->
+              RepeatedPtrFieldBase::SpaceUsedExcludingSelf<
+                GenericTypeHandler<Message> >();
+        break;
+    }
+  } else {
+    switch (cpp_type(type)) {
+      case WireFormatLite::CPPTYPE_STRING:
+        total_size += sizeof(*string_value) +
+                      StringSpaceUsedExcludingSelf(*string_value);
+        break;
+      case WireFormatLite::CPPTYPE_MESSAGE:
+        total_size += down_cast<Message*>(message_value)->SpaceUsed();
+        break;
+      default:
+        // No extra storage costs for primitive types.
+        break;
+    }
+  }
+  return total_size;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 0cd367d..d294e58 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -38,6 +38,7 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -220,8 +221,36 @@
     const FieldDescriptor* field = descriptor_->field(i);
 
     if (field->is_repeated()) {
-      total_size += GetRaw<GenericRepeatedField>(message, field)
-                      .GenericSpaceUsedExcludingSelf();
+      switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+        case FieldDescriptor::CPPTYPE_##UPPERCASE :                           \
+          total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field)     \
+                          .SpaceUsedExcludingSelf();                          \
+          break
+
+        HANDLE_TYPE( INT32,  int32);
+        HANDLE_TYPE( INT64,  int64);
+        HANDLE_TYPE(UINT32, uint32);
+        HANDLE_TYPE(UINT64, uint64);
+        HANDLE_TYPE(DOUBLE, double);
+        HANDLE_TYPE( FLOAT,  float);
+        HANDLE_TYPE(  BOOL,   bool);
+        HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+        case FieldDescriptor::CPPTYPE_STRING:
+            total_size += GetRaw<RepeatedPtrField<string> >(message, field)
+                            .SpaceUsedExcludingSelf();
+          break;
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          // We don't know which subclass of RepeatedPtrFieldBase the type is,
+          // so we use RepeatedPtrFieldBase directly.
+          total_size +=
+              GetRaw<RepeatedPtrFieldBase>(message, field)
+                .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+          break;
+      }
     } else {
       switch (field->cpp_type()) {
         case FieldDescriptor::CPPTYPE_INT32 :
@@ -274,25 +303,59 @@
     Message* message2) const {
   if (message1 == message2) return;
 
+  // TODO(kenton):  Other Reflection methods should probably check this too.
   GOOGLE_CHECK_EQ(message1->GetReflection(), this)
-    << "Tried to swap using reflection object incompatible with message1.";
-
+    << "First argument to Swap() (of type \""
+    << message1->GetDescriptor()->full_name()
+    << "\") is not compatible with this reflection object (which is for type \""
+    << descriptor_->full_name()
+    << "\").  Note that the exact same class is required; not just the same "
+       "descriptor.";
   GOOGLE_CHECK_EQ(message2->GetReflection(), this)
-    << "Tried to swap using reflection object incompatible with message2.";
+    << "Second argument to Swap() (of type \""
+    << message1->GetDescriptor()->full_name()
+    << "\") is not compatible with this reflection object (which is for type \""
+    << descriptor_->full_name()
+    << "\").  Note that the exact same class is required; not just the same "
+       "descriptor.";
 
   uint32* has_bits1 = MutableHasBits(message1);
   uint32* has_bits2 = MutableHasBits(message2);
   int has_bits_size = (descriptor_->field_count() + 31) / 32;
 
   for (int i = 0; i < has_bits_size; i++) {
-    std::swap(has_bits1[i], has_bits2[i]);
+    swap(has_bits1[i], has_bits2[i]);
   }
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->is_repeated()) {
-      MutableRaw<GenericRepeatedField>(message1, field)->GenericSwap(
-          MutableRaw<GenericRepeatedField>(message2, field));
+      switch (field->cpp_type()) {
+#define SWAP_ARRAYS(CPPTYPE, TYPE)                                           \
+        case FieldDescriptor::CPPTYPE_##CPPTYPE:                             \
+          MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap(           \
+              MutableRaw<RepeatedField<TYPE> >(message2, field));            \
+          break;
+
+          SWAP_ARRAYS(INT32 , int32 );
+          SWAP_ARRAYS(INT64 , int64 );
+          SWAP_ARRAYS(UINT32, uint32);
+          SWAP_ARRAYS(UINT64, uint64);
+          SWAP_ARRAYS(FLOAT , float );
+          SWAP_ARRAYS(DOUBLE, double);
+          SWAP_ARRAYS(BOOL  , bool  );
+          SWAP_ARRAYS(ENUM  , int   );
+#undef SWAP_ARRAYS
+
+        case FieldDescriptor::CPPTYPE_STRING:
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
+              MutableRaw<RepeatedPtrFieldBase>(message2, field));
+          break;
+
+        default:
+          GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+      }
     } else {
       switch (field->cpp_type()) {
 #define SWAP_VALUES(CPPTYPE, TYPE)                                           \
@@ -300,6 +363,7 @@
           swap(*MutableRaw<TYPE>(message1, field),                           \
                *MutableRaw<TYPE>(message2, field));                          \
           break;
+
           SWAP_VALUES(INT32 , int32 );
           SWAP_VALUES(INT64 , int64 );
           SWAP_VALUES(UINT32, uint32);
@@ -307,10 +371,15 @@
           SWAP_VALUES(FLOAT , float );
           SWAP_VALUES(DOUBLE, double);
           SWAP_VALUES(BOOL  , bool  );
-          SWAP_VALUES(ENUM  , int32 );
-          SWAP_VALUES(STRING, string*);
+          SWAP_VALUES(ENUM  , int   );
           SWAP_VALUES(MESSAGE, Message*);
-#undef SWAP_PRIMITIVE_VALUES
+#undef SWAP_VALUES
+
+        case FieldDescriptor::CPPTYPE_STRING:
+            swap(*MutableRaw<string*>(message1, field),
+                 *MutableRaw<string*>(message2, field));
+          break;
+
         default:
           GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
       }
@@ -346,7 +415,28 @@
   if (field->is_extension()) {
     return GetExtensionSet(message).ExtensionSize(field->number());
   } else {
-    return GetRaw<GenericRepeatedField>(message, field).GenericSize();
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        return GetRaw<RepeatedField<LOWERCASE> >(message, field).size()
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        return GetRaw<RepeatedPtrFieldBase>(message, field).size();
+    }
+
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return 0;
   }
 }
 
@@ -401,7 +491,35 @@
       }
     }
   } else {
-    MutableRaw<GenericRepeatedField>(message, field)->GenericClear();
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear();       \
+        break
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING: {
+          MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_MESSAGE: {
+        // We don't know which subclass of RepeatedPtrFieldBase the type is,
+        // so we use RepeatedPtrFieldBase directly.
+        MutableRaw<RepeatedPtrFieldBase>(message, field)
+            ->Clear<GenericTypeHandler<Message> >();
+        break;
+      }
+    }
   }
 }
 
@@ -414,7 +532,31 @@
   if (field->is_extension()) {
     MutableExtensionSet(message)->RemoveLast(field->number());
   } else {
-    MutableRaw<GenericRepeatedField>(message, field)->GenericRemoveLast();
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast();  \
+        break
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING:
+          MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
+        break;
+
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        MutableRaw<RepeatedPtrFieldBase>(message, field)
+            ->RemoveLast<GenericTypeHandler<Message> >();
+        break;
+    }
   }
 }
 
@@ -427,11 +569,31 @@
   USAGE_CHECK_REPEATED(Swap);
 
   if (field->is_extension()) {
-    MutableExtensionSet(message)->SwapElements(
-                                      field->number(), index1, index2);
+    MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
   } else {
-    MutableRaw<GenericRepeatedField>(message, field)->GenericSwapElements(
-                                                            index1, index2);
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        MutableRaw<RepeatedField<LOWERCASE> >(message, field)                 \
+            ->SwapElements(index1, index2);                                   \
+        break
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        MutableRaw<RepeatedPtrFieldBase>(message, field)
+            ->SwapElements(index1, index2);
+        break;
+    }
   }
 }
 
@@ -456,7 +618,7 @@
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->is_repeated()) {
-      if (GetRaw<GenericRepeatedField>(message, field).GenericSize() > 0) {
+      if (FieldSize(message, field) > 0) {
         output->push_back(field);
       }
     } else {
@@ -597,7 +759,7 @@
   if (field->is_extension()) {
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
   } else {
-    return GetRepeatedField<string>(message, field, index);
+    return GetRepeatedPtrField<string>(message, field, index);
   }
 }
 
@@ -608,7 +770,7 @@
   if (field->is_extension()) {
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
   } else {
-    return GetRepeatedField<string>(message, field, index);
+    return GetRepeatedPtrField<string>(message, field, index);
   }
 }
 
@@ -621,7 +783,7 @@
     MutableExtensionSet(message)->SetRepeatedString(
       field->number(), index, value);
   } else {
-    SetRepeatedField<string>(message, field, index, value);
+    *MutableRepeatedField<string>(message, field, index) = value;
   }
 }
 
@@ -634,7 +796,7 @@
     MutableExtensionSet(message)->AddString(field->number(),
                                             field->type(), value);
   } else {
-    AddField<string>(message, field, value);
+    *AddField<string>(message, field) = value;
   }
 }
 
@@ -725,9 +887,10 @@
   USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
 
   if (field->is_extension()) {
-    return GetExtensionSet(message).GetMessage(field->number(),
-                                               field->message_type(),
-                                               message_factory_);
+    return static_cast<const Message&>(
+      GetExtensionSet(message).GetMessage(field->number(),
+                                          field->message_type(),
+                                          message_factory_));
   } else {
     const Message* result = GetRaw<const Message*>(message, field);
     if (result == NULL) {
@@ -742,10 +905,11 @@
   USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
 
   if (field->is_extension()) {
-    return MutableExtensionSet(message)->MutableMessage(field->number(),
-                                                        field->type(),
-                                                        field->message_type(),
-                                                        message_factory_);
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->MutableMessage(field->number(),
+                                                     field->type(),
+                                                     field->message_type(),
+                                                     message_factory_));
   } else {
     Message** result = MutableField<Message*>(message, field);
     if (*result == NULL) {
@@ -761,9 +925,11 @@
   USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
-    return GetExtensionSet(message).GetRepeatedMessage(field->number(), index);
+    return static_cast<const Message&>(
+        GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
   } else {
-    return GetRepeatedField<Message>(message, field, index);
+    return GetRaw<RepeatedPtrFieldBase>(message, field)
+        .Get<GenericTypeHandler<Message> >(index);
   }
 }
 
@@ -772,10 +938,12 @@
   USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
-    return MutableExtensionSet(message)->MutableRepeatedMessage(
-      field->number(), index);
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->MutableRepeatedMessage(
+          field->number(), index));
   } else {
-    return MutableRepeatedField<Message>(message, field, index);
+    return MutableRaw<RepeatedPtrFieldBase>(message, field)
+        ->Mutable<GenericTypeHandler<Message> >(index);
   }
 }
 
@@ -784,12 +952,29 @@
   USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
-    return MutableExtensionSet(message)->AddMessage(field->number(),
-                                                    field->type(),
-                                                    field->message_type(),
-                                                    message_factory_);
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->AddMessage(field->number(),
+                                                 field->type(),
+                                                 field->message_type(),
+                                                 message_factory_));
   } else {
-    return AddField<Message>(message, field);
+    // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
+    // know how to allocate one.
+    RepeatedPtrFieldBase* repeated =
+      MutableRaw<RepeatedPtrFieldBase>(message, field);
+    Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
+    if (result == NULL) {
+      // We must allocate a new object.
+      const Message* prototype;
+      if (repeated->size() == 0) {
+        prototype = message_factory_->GetPrototype(field->message_type());
+      } else {
+        prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
+      }
+      result = prototype->New();
+      repeated->AddAllocated<GenericTypeHandler<Message> >(result);
+    }
+    return result;
   }
 }
 
@@ -925,46 +1110,46 @@
 }
 
 template <typename Type>
-inline const Type& GeneratedMessageReflection::GetRepeatedField(
+inline Type GeneratedMessageReflection::GetRepeatedField(
     const Message& message, const FieldDescriptor* field, int index) const {
-  return *reinterpret_cast<const Type*>(
-    GetRaw<GenericRepeatedField>(message, field).GenericGet(index));
+  return GetRaw<RepeatedField<Type> >(message, field).Get(index);
+}
+
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetRepeatedPtrField(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
 }
 
 template <typename Type>
 inline void GeneratedMessageReflection::SetRepeatedField(
     Message* message, const FieldDescriptor* field,
-    int index, const Type& value) const {
-  GenericRepeatedField* repeated =
-    MutableRaw<GenericRepeatedField>(message, field);
-  *reinterpret_cast<Type*>(repeated->GenericMutable(index)) = value;
+    int index, Type value) const {
+  MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
 }
 
 template <typename Type>
 inline Type* GeneratedMessageReflection::MutableRepeatedField(
     Message* message, const FieldDescriptor* field, int index) const {
-  GenericRepeatedField* repeated =
-    MutableRaw<GenericRepeatedField>(message, field);
-  return reinterpret_cast<Type*>(repeated->GenericMutable(index));
+  RepeatedPtrField<Type>* repeated =
+    MutableRaw<RepeatedPtrField<Type> >(message, field);
+  return repeated->Mutable(index);
 }
 
 template <typename Type>
 inline void GeneratedMessageReflection::AddField(
-    Message* message, const FieldDescriptor* field, const Type& value) const {
-  GenericRepeatedField* repeated =
-    MutableRaw<GenericRepeatedField>(message, field);
-  *reinterpret_cast<Type*>(repeated->GenericAdd()) = value;
+    Message* message, const FieldDescriptor* field, Type value) const {
+  MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
 }
 
 template <typename Type>
 inline Type* GeneratedMessageReflection::AddField(
     Message* message, const FieldDescriptor* field) const {
-  GenericRepeatedField* repeated =
-    MutableRaw<GenericRepeatedField>(message, field);
-  return reinterpret_cast<Type*>(repeated->GenericAdd());
+  RepeatedPtrField<Type>* repeated =
+    MutableRaw<RepeatedPtrField<Type> >(message, field);
+  return repeated->Add();
 }
 
-
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 702f189..d0b5b43 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -142,7 +142,7 @@
   void ClearField(Message* message, const FieldDescriptor* field) const;
   void RemoveLast(Message* message, const FieldDescriptor* field) const;
   void Swap(Message* message1, Message* message2) const;
-  void SwapElements(Message* message, const FieldDescriptor* field, 
+  void SwapElements(Message* message, const FieldDescriptor* field,
             int index1, int index2) const;
   void ListFields(const Message& message,
                   vector<const FieldDescriptor*>* output) const;
@@ -314,20 +314,24 @@
   inline Type* MutableField(Message* message,
                             const FieldDescriptor* field) const;
   template <typename Type>
-  inline const Type& GetRepeatedField(const Message& message,
-                                      const FieldDescriptor* field,
-                                      int index) const;
+  inline Type GetRepeatedField(const Message& message,
+                               const FieldDescriptor* field,
+                               int index) const;
+  template <typename Type>
+  inline const Type& GetRepeatedPtrField(const Message& message,
+                                         const FieldDescriptor* field,
+                                         int index) const;
   template <typename Type>
   inline void SetRepeatedField(Message* message,
                                const FieldDescriptor* field, int index,
-                               const Type& value) const;
+                               Type value) const;
   template <typename Type>
   inline Type* MutableRepeatedField(Message* message,
                                     const FieldDescriptor* field,
                                     int index) const;
   template <typename Type>
   inline void AddField(Message* message,
-                       const FieldDescriptor* field, const Type& value) const;
+                       const FieldDescriptor* field, Type value) const;
   template <typename Type>
   inline Type* AddField(Message* message,
                         const FieldDescriptor* field) const;
@@ -388,11 +392,6 @@
 #endif
 }
 
-// Compute the space used by a string, not including sizeof(string) itself.
-// This is slightly complicated because small strings store their data within
-// the string object but large strings do not.
-LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
-
 // Helper for EnumType_Parse functions: try to parse the string 'name' as an
 // enum name of the given type, returning true and filling in value on success,
 // or returning false and leaving value unchanged on failure.
@@ -415,7 +414,6 @@
 // descriptor.h.
 LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
 
-
 }  // namespace internal
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
new file mode 100644
index 0000000..9470bb0
--- /dev/null
+++ b/src/google/protobuf/generated_message_util.cc
@@ -0,0 +1,44 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/generated_message_util.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
new file mode 100644
index 0000000..80dd028
--- /dev/null
+++ b/src/google/protobuf/generated_message_util.h
@@ -0,0 +1,65 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains miscellaneous helper code used by generated code --
+// including lite types -- but which should not be used directly by users.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Annotation for the compiler to emit a deprecation message if a field marked
+// with option 'deprecated=true' is used in the code.
+//
+// For internal use in the pb.cc files, deprecation warnings are suppressed
+// there.
+#undef DEPRECATED_PROTOBUF_FIELD
+#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION)
+#  define DEPRECATED_PROTOBUF_FIELD GOOGLE_ATTRIBUTE_DEPRECATED
+#else
+#  define DEPRECATED_PROTOBUF_FIELD
+#endif
+
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 0a00d2b..e17a477 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -80,18 +80,49 @@
     total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
     recursion_depth_(0),
     recursion_limit_(kDefaultRecursionLimit) {
+  // Eagerly Refresh() so buffer space is immediately available.
+  Refresh();
+}
+
+CodedInputStream::CodedInputStream(const uint8* buffer, int size)
+  : input_(NULL),
+    buffer_(buffer),
+    buffer_size_(size),
+    total_bytes_read_(size),
+    overflow_bytes_(0),
+    last_tag_(0),
+    legitimate_message_end_(false),
+    aliasing_enabled_(false),
+    current_limit_(size),
+    buffer_size_after_limit_(0),
+    total_bytes_limit_(kDefaultTotalBytesLimit),
+    total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
+    recursion_depth_(0),
+    recursion_limit_(kDefaultRecursionLimit) {
+  // Note that setting current_limit_ == size is important to prevent some
+  // code paths from trying to access input_ and segfaulting.
 }
 
 CodedInputStream::~CodedInputStream() {
-  int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
-  if (backup_bytes > 0) {
-    // We still have bytes left over from the last buffer.  Back up over
-    // them.
-    input_->BackUp(backup_bytes);
+  if (input_ != NULL) {
+    BackUpInputToCurrentPosition();
   }
 }
 
 
+void CodedInputStream::BackUpInputToCurrentPosition() {
+  int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
+  if (backup_bytes > 0) {
+    input_->BackUp(backup_bytes);
+
+    // total_bytes_read_ doesn't include overflow_bytes_.
+    total_bytes_read_ -= buffer_size_ + buffer_size_after_limit_;
+    buffer_size_ = 0;
+    buffer_size_after_limit_ = 0;
+    overflow_bytes_ = 0;
+  }
+}
+
 inline void CodedInputStream::RecomputeBufferLimits() {
   buffer_size_ += buffer_size_after_limit_;
   int closest_limit = min(current_limit_, total_bytes_limit_);
@@ -193,8 +224,10 @@
   int bytes_until_limit = closest_limit - total_bytes_read_;
   if (bytes_until_limit < count) {
     // We hit the limit.  Skip up to it then fail.
-    total_bytes_read_ = closest_limit;
-    input_->Skip(bytes_until_limit);
+    if (bytes_until_limit > 0) {
+      total_bytes_read_ = closest_limit;
+      input_->Skip(bytes_until_limit);
+    }
     return false;
   }
 
@@ -216,6 +249,7 @@
     memcpy(buffer, buffer_, buffer_size_);
     buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
     size -= buffer_size_;
+    Advance(buffer_size_);
     if (!Refresh()) return false;
   }
 
@@ -247,6 +281,7 @@
       buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
     }
     size -= buffer_size_;
+    Advance(buffer_size_);
     if (!Refresh()) return false;
   }
 
@@ -441,11 +476,11 @@
 }
 
 bool CodedInputStream::Refresh() {
-  if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0) {
-    // We've hit a limit.  Stop.
-    buffer_ += buffer_size_;
-    buffer_size_ = 0;
+  GOOGLE_DCHECK_EQ(buffer_size_, 0);
 
+  if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
+      total_bytes_read_ == current_limit_) {
+    // We've hit a limit.  Stop.
     int current_position = total_bytes_read_ - buffer_size_after_limit_;
 
     if (current_position >= total_bytes_limit_ &&
@@ -570,10 +605,7 @@
   bool use_fast = buffer_size_ >= sizeof(value);
   uint8* ptr = use_fast ? buffer_ : bytes;
 
-  ptr[0] = static_cast<uint8>(value      );
-  ptr[1] = static_cast<uint8>(value >>  8);
-  ptr[2] = static_cast<uint8>(value >> 16);
-  ptr[3] = static_cast<uint8>(value >> 24);
+  WriteLittleEndian32ToArray(value, ptr);
 
   if (use_fast) {
     Advance(sizeof(value));
@@ -582,32 +614,13 @@
   }
 }
 
-uint8* CodedOutputStream::WriteLittleEndian32ToArray(
-    uint32 value, uint8* target) {
-  target[0] = static_cast<uint8>(value      );
-  target[1] = static_cast<uint8>(value >>  8);
-  target[2] = static_cast<uint8>(value >> 16);
-  target[3] = static_cast<uint8>(value >> 24);
-  return target + sizeof(value);
-}
-
 void CodedOutputStream::WriteLittleEndian64(uint64 value) {
   uint8 bytes[sizeof(value)];
 
-  uint32 part0 = static_cast<uint32>(value);
-  uint32 part1 = static_cast<uint32>(value >> 32);
-
   bool use_fast = buffer_size_ >= sizeof(value);
   uint8* ptr = use_fast ? buffer_ : bytes;
 
-  ptr[0] = static_cast<uint8>(part0      );
-  ptr[1] = static_cast<uint8>(part0 >>  8);
-  ptr[2] = static_cast<uint8>(part0 >> 16);
-  ptr[3] = static_cast<uint8>(part0 >> 24);
-  ptr[4] = static_cast<uint8>(part1      );
-  ptr[5] = static_cast<uint8>(part1 >>  8);
-  ptr[6] = static_cast<uint8>(part1 >> 16);
-  ptr[7] = static_cast<uint8>(part1 >> 24);
+  WriteLittleEndian64ToArray(value, ptr);
 
   if (use_fast) {
     Advance(sizeof(value));
@@ -616,23 +629,6 @@
   }
 }
 
-uint8* CodedOutputStream::WriteLittleEndian64ToArray(
-    uint64 value, uint8* target) {
-  uint32 part0 = static_cast<uint32>(value);
-  uint32 part1 = static_cast<uint32>(value >> 32);
-
-  target[0] = static_cast<uint8>(part0      );
-  target[1] = static_cast<uint8>(part0 >>  8);
-  target[2] = static_cast<uint8>(part0 >> 16);
-  target[3] = static_cast<uint8>(part0 >> 24);
-  target[4] = static_cast<uint8>(part1      );
-  target[5] = static_cast<uint8>(part1 >>  8);
-  target[6] = static_cast<uint8>(part1 >> 16);
-  target[7] = static_cast<uint8>(part1 >> 24);
-
-  return target + sizeof(value);
-}
-
 inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
     uint32 value, uint8* target) {
   target[0] = static_cast<uint8>(value | 0x80);
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 9e45021..fa023f3 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -110,6 +110,9 @@
 #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
 
 #include <string>
+#ifndef _MSC_VER
+#include <sys/param.h>
+#endif  // !_MSC_VER
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -137,6 +140,11 @@
   // Create a CodedInputStream that reads from the given ZeroCopyInputStream.
   explicit CodedInputStream(ZeroCopyInputStream* input);
 
+  // Create a CodedInputStream that reads from the given flat array.  This is
+  // faster than using an ArrayInputStream.  PushLimit(size) is implied by
+  // this constructor.
+  explicit CodedInputStream(const uint8* buffer, int size);
+
   // Destroy the CodedInputStream and position the underlying
   // ZeroCopyInputStream at the first unread byte.  If an error occurred while
   // reading (causing a method to return false), then the exact position of
@@ -360,6 +368,9 @@
   // Advance the buffer by a given number of bytes.
   void Advance(int amount);
 
+  // Back up input_ to the current buffer position.
+  void BackUpInputToCurrentPosition();
+
   // Recomputes the value of buffer_size_after_limit_.  Must be called after
   // current_limit_ or total_bytes_limit_ changes.
   void RecomputeBufferLimits();
@@ -664,6 +675,41 @@
   }
 }
 
+inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
+                                                            uint8* target) {
+#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
+    defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+  memcpy(target, &value, sizeof(value));
+#else
+  target[0] = static_cast<uint8>(value      );
+  target[1] = static_cast<uint8>(value >>  8);
+  target[2] = static_cast<uint8>(value >> 16);
+  target[3] = static_cast<uint8>(value >> 24);
+#endif
+  return target + sizeof(value);
+}
+
+inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
+                                                            uint8* target) {
+#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
+    defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+  memcpy(target, &value, sizeof(value));
+#else
+  uint32 part0 = static_cast<uint32>(value);
+  uint32 part1 = static_cast<uint32>(value >> 32);
+
+  target[0] = static_cast<uint8>(part0      );
+  target[1] = static_cast<uint8>(part0 >>  8);
+  target[2] = static_cast<uint8>(part0 >> 16);
+  target[3] = static_cast<uint8>(part0 >> 24);
+  target[4] = static_cast<uint8>(part1      );
+  target[5] = static_cast<uint8>(part1 >>  8);
+  target[6] = static_cast<uint8>(part1 >> 16);
+  target[7] = static_cast<uint8>(part1 >> 24);
+#endif
+  return target + sizeof(value);
+}
+
 inline void CodedOutputStream::WriteTag(uint32 value) {
   WriteVarint32(value);
 }
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index d8d0e70..243b3e3 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -1,5 +1,5 @@
 // Protocol Buffers - Google's data interchange format
-// Copyright 2009 Google Inc.  All rights reserved.
+// Copyright 2008 Google Inc.  All rights reserved.
 // http://code.google.com/p/protobuf/
 //
 // Redistribution and use in source and binary forms, with or without
@@ -29,8 +29,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Author: brianolson@google.com (Brian Olson)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
 //
 // This file contains the implementation of classes GzipInputStream and
 // GzipOutputStream.
@@ -39,6 +37,7 @@
 
 #if HAVE_ZLIB
 #include <google/protobuf/io/gzip_stream.h>
+
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -291,6 +290,6 @@
 
 }  // namespace io
 }  // namespace protobuf
-}  // namespace google
 
 #endif  // HAVE_ZLIB
+}  // namespace google
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index 4f29499..50a2ad7 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -1,5 +1,5 @@
 // Protocol Buffers - Google's data interchange format
-// Copyright 2009 Google Inc.  All rights reserved.
+// Copyright 2008 Google Inc.  All rights reserved.
 // http://code.google.com/p/protobuf/
 //
 // Redistribution and use in source and binary forms, with or without
@@ -29,8 +29,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Author: brianolson@google.com (Brian Olson)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
 //
 // This file contains the definition for classes GzipInputStream and
 // GzipOutputStream.
@@ -173,6 +171,6 @@
 
 }  // namespace io
 }  // namespace protobuf
-}  // namespace google
 
+}  // namespace google
 #endif  // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 4823912..0bda451 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -571,7 +571,7 @@
   const char* ptr = text.c_str();
   int base = 10;
   if (ptr[0] == '0') {
-    if (ptr[1] == 'x') {
+    if (ptr[1] == 'x' || ptr[1] == 'X') {
       // This is hex.
       base = 16;
       ptr += 2;
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index dd7ed5c..eac1455 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -487,6 +487,7 @@
   EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12"));
   EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF"));
   EXPECT_EQ(01234567, ParseInteger("01234567"));
+  EXPECT_EQ(0X123, ParseInteger("0X123"));
 
   // Test invalid integers that may still be tokenized as integers.
   EXPECT_EQ(0, ParseInteger("0x"));
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index 0b4516e..1384c74 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -60,7 +60,6 @@
 
 namespace {
 
-
 // EINTR sucks.
 int close_no_eintr(int fd) {
   int result;
@@ -70,352 +69,8 @@
   return result;
 }
 
-// Default block size for Copying{In,Out}putStreamAdaptor.
-static const int kDefaultBlockSize = 8192;
-
 }  // namespace
 
-// ===================================================================
-
-ArrayInputStream::ArrayInputStream(const void* data, int size,
-                                   int block_size)
-  : data_(reinterpret_cast<const uint8*>(data)),
-    size_(size),
-    block_size_(block_size > 0 ? block_size : size),
-    position_(0),
-    last_returned_size_(0) {
-}
-
-ArrayInputStream::~ArrayInputStream() {
-}
-
-bool ArrayInputStream::Next(const void** data, int* size) {
-  if (position_ < size_) {
-    last_returned_size_ = min(block_size_, size_ - position_);
-    *data = data_ + position_;
-    *size = last_returned_size_;
-    position_ += last_returned_size_;
-    return true;
-  } else {
-    // We're at the end of the array.
-    last_returned_size_ = 0;   // Don't let caller back up.
-    return false;
-  }
-}
-
-void ArrayInputStream::BackUp(int count) {
-  GOOGLE_CHECK_GT(last_returned_size_, 0)
-      << "BackUp() can only be called after a successful Next().";
-  GOOGLE_CHECK_LE(count, last_returned_size_);
-  GOOGLE_CHECK_GE(count, 0);
-  position_ -= count;
-  last_returned_size_ = 0;  // Don't let caller back up further.
-}
-
-bool ArrayInputStream::Skip(int count) {
-  GOOGLE_CHECK_GE(count, 0);
-  last_returned_size_ = 0;   // Don't let caller back up.
-  if (count > size_ - position_) {
-    position_ = size_;
-    return false;
-  } else {
-    position_ += count;
-    return true;
-  }
-}
-
-int64 ArrayInputStream::ByteCount() const {
-  return position_;
-}
-
-
-// ===================================================================
-
-ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
-  : data_(reinterpret_cast<uint8*>(data)),
-    size_(size),
-    block_size_(block_size > 0 ? block_size : size),
-    position_(0),
-    last_returned_size_(0) {
-}
-
-ArrayOutputStream::~ArrayOutputStream() {
-}
-
-bool ArrayOutputStream::Next(void** data, int* size) {
-  if (position_ < size_) {
-    last_returned_size_ = min(block_size_, size_ - position_);
-    *data = data_ + position_;
-    *size = last_returned_size_;
-    position_ += last_returned_size_;
-    return true;
-  } else {
-    // We're at the end of the array.
-    last_returned_size_ = 0;   // Don't let caller back up.
-    return false;
-  }
-}
-
-void ArrayOutputStream::BackUp(int count) {
-  GOOGLE_CHECK_GT(last_returned_size_, 0)
-      << "BackUp() can only be called after a successful Next().";
-  GOOGLE_CHECK_LE(count, last_returned_size_);
-  GOOGLE_CHECK_GE(count, 0);
-  position_ -= count;
-  last_returned_size_ = 0;  // Don't let caller back up further.
-}
-
-int64 ArrayOutputStream::ByteCount() const {
-  return position_;
-}
-
-// ===================================================================
-
-StringOutputStream::StringOutputStream(string* target)
-  : target_(target) {
-}
-
-StringOutputStream::~StringOutputStream() {
-}
-
-bool StringOutputStream::Next(void** data, int* size) {
-  int old_size = target_->size();
-
-  // Grow the string.
-  if (old_size < target_->capacity()) {
-    // Resize the string to match its capacity, since we can get away
-    // without a memory allocation this way.
-    STLStringResizeUninitialized(target_, target_->capacity());
-  } else {
-    // Size has reached capacity, so double the size.  Also make sure
-    // that the new size is at least kMinimumSize.
-    STLStringResizeUninitialized(
-      target_,
-      max(old_size * 2,
-          kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
-  }
-
-  *data = string_as_array(target_) + old_size;
-  *size = target_->size() - old_size;
-  return true;
-}
-
-void StringOutputStream::BackUp(int count) {
-  GOOGLE_CHECK_GE(count, 0);
-  GOOGLE_CHECK_LE(count, target_->size());
-  target_->resize(target_->size() - count);
-}
-
-int64 StringOutputStream::ByteCount() const {
-  return target_->size();
-}
-
-// ===================================================================
-
-
-// ===================================================================
-
-CopyingInputStream::~CopyingInputStream() {}
-
-int CopyingInputStream::Skip(int count) {
-  char junk[4096];
-  int skipped = 0;
-  while (skipped < count) {
-    int bytes = Read(junk, min(count - skipped,
-                               implicit_cast<int>(sizeof(junk))));
-    if (bytes <= 0) {
-      // EOF or read error.
-      return skipped;
-    }
-    skipped += bytes;
-  }
-  return skipped;
-}
-
-CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
-    CopyingInputStream* copying_stream, int block_size)
-  : copying_stream_(copying_stream),
-    owns_copying_stream_(false),
-    failed_(false),
-    position_(0),
-    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
-    buffer_used_(0),
-    backup_bytes_(0) {
-}
-
-CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
-  if (owns_copying_stream_) {
-    delete copying_stream_;
-  }
-}
-
-bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
-  if (failed_) {
-    // Already failed on a previous read.
-    return false;
-  }
-
-  AllocateBufferIfNeeded();
-
-  if (backup_bytes_ > 0) {
-    // We have data left over from a previous BackUp(), so just return that.
-    *data = buffer_.get() + buffer_used_ - backup_bytes_;
-    *size = backup_bytes_;
-    backup_bytes_ = 0;
-    return true;
-  }
-
-  // Read new data into the buffer.
-  buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
-  if (buffer_used_ <= 0) {
-    // EOF or read error.  We don't need the buffer anymore.
-    if (buffer_used_ < 0) {
-      // Read error (not EOF).
-      failed_ = true;
-    }
-    FreeBuffer();
-    return false;
-  }
-  position_ += buffer_used_;
-
-  *size = buffer_used_;
-  *data = buffer_.get();
-  return true;
-}
-
-void CopyingInputStreamAdaptor::BackUp(int count) {
-  GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
-    << " BackUp() can only be called after Next().";
-  GOOGLE_CHECK_LE(count, buffer_used_)
-    << " Can't back up over more bytes than were returned by the last call"
-       " to Next().";
-  GOOGLE_CHECK_GE(count, 0)
-    << " Parameter to BackUp() can't be negative.";
-
-  backup_bytes_ = count;
-}
-
-bool CopyingInputStreamAdaptor::Skip(int count) {
-  GOOGLE_CHECK_GE(count, 0);
-
-  if (failed_) {
-    // Already failed on a previous read.
-    return false;
-  }
-
-  // First skip any bytes left over from a previous BackUp().
-  if (backup_bytes_ >= count) {
-    // We have more data left over than we're trying to skip.  Just chop it.
-    backup_bytes_ -= count;
-    return true;
-  }
-
-  count -= backup_bytes_;
-  backup_bytes_ = 0;
-
-  int skipped = copying_stream_->Skip(count);
-  position_ += skipped;
-  return skipped == count;
-}
-
-int64 CopyingInputStreamAdaptor::ByteCount() const {
-  return position_ - backup_bytes_;
-}
-
-void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
-  if (buffer_.get() == NULL) {
-    buffer_.reset(new uint8[buffer_size_]);
-  }
-}
-
-void CopyingInputStreamAdaptor::FreeBuffer() {
-  GOOGLE_CHECK_EQ(backup_bytes_, 0);
-  buffer_used_ = 0;
-  buffer_.reset();
-}
-
-// ===================================================================
-
-CopyingOutputStream::~CopyingOutputStream() {}
-
-CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
-    CopyingOutputStream* copying_stream, int block_size)
-  : copying_stream_(copying_stream),
-    owns_copying_stream_(false),
-    failed_(false),
-    position_(0),
-    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
-    buffer_used_(0) {
-}
-
-CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
-  WriteBuffer();
-  if (owns_copying_stream_) {
-    delete copying_stream_;
-  }
-}
-
-bool CopyingOutputStreamAdaptor::Flush() {
-  return WriteBuffer();
-}
-
-bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
-  if (buffer_used_ == buffer_size_) {
-    if (!WriteBuffer()) return false;
-  }
-
-  AllocateBufferIfNeeded();
-
-  *data = buffer_.get() + buffer_used_;
-  *size = buffer_size_ - buffer_used_;
-  buffer_used_ = buffer_size_;
-  return true;
-}
-
-void CopyingOutputStreamAdaptor::BackUp(int count) {
-  GOOGLE_CHECK_GE(count, 0);
-  GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
-    << " BackUp() can only be called after Next().";
-  GOOGLE_CHECK_LE(count, buffer_used_)
-    << " Can't back up over more bytes than were returned by the last call"
-       " to Next().";
-
-  buffer_used_ -= count;
-}
-
-int64 CopyingOutputStreamAdaptor::ByteCount() const {
-  return position_ + buffer_used_;
-}
-
-bool CopyingOutputStreamAdaptor::WriteBuffer() {
-  if (failed_) {
-    // Already failed on a previous write.
-    return false;
-  }
-
-  if (buffer_used_ == 0) return true;
-
-  if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
-    position_ += buffer_used_;
-    buffer_used_ = 0;
-    return true;
-  } else {
-    failed_ = true;
-    FreeBuffer();
-    return false;
-  }
-}
-
-void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
-  if (buffer_ == NULL) {
-    buffer_.reset(new uint8[buffer_size_]);
-  }
-}
-
-void CopyingOutputStreamAdaptor::FreeBuffer() {
-  buffer_used_ = 0;
-  buffer_.reset();
-}
 
 // ===================================================================
 
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
index 448aa21..d7cf73f 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -45,6 +45,7 @@
 #include <string>
 #include <iosfwd>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/stubs/common.h>
 
 
@@ -52,285 +53,6 @@
 namespace protobuf {
 namespace io {
 
-// ===================================================================
-
-// A ZeroCopyInputStream backed by an in-memory array of bytes.
-class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
- public:
-  // Create an InputStream that returns the bytes pointed to by "data".
-  // "data" remains the property of the caller but must remain valid until
-  // the stream is destroyed.  If a block_size is given, calls to Next()
-  // will return data blocks no larger than the given size.  Otherwise, the
-  // first call to Next() returns the entire array.  block_size is mainly
-  // useful for testing; in production you would probably never want to set
-  // it.
-  ArrayInputStream(const void* data, int size, int block_size = -1);
-  ~ArrayInputStream();
-
-  // implements ZeroCopyInputStream ----------------------------------
-  bool Next(const void** data, int* size);
-  void BackUp(int count);
-  bool Skip(int count);
-  int64 ByteCount() const;
-
-
- private:
-  const uint8* const data_;  // The byte array.
-  const int size_;           // Total size of the array.
-  const int block_size_;     // How many bytes to return at a time.
-
-  int position_;
-  int last_returned_size_;   // How many bytes we returned last time Next()
-                             // was called (used for error checking only).
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
-};
-
-// ===================================================================
-
-// A ZeroCopyOutputStream backed by an in-memory array of bytes.
-class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
- public:
-  // Create an OutputStream that writes to the bytes pointed to by "data".
-  // "data" remains the property of the caller but must remain valid until
-  // the stream is destroyed.  If a block_size is given, calls to Next()
-  // will return data blocks no larger than the given size.  Otherwise, the
-  // first call to Next() returns the entire array.  block_size is mainly
-  // useful for testing; in production you would probably never want to set
-  // it.
-  ArrayOutputStream(void* data, int size, int block_size = -1);
-  ~ArrayOutputStream();
-
-  // implements ZeroCopyOutputStream ---------------------------------
-  bool Next(void** data, int* size);
-  void BackUp(int count);
-  int64 ByteCount() const;
-
- private:
-  uint8* const data_;        // The byte array.
-  const int size_;           // Total size of the array.
-  const int block_size_;     // How many bytes to return at a time.
-
-  int position_;
-  int last_returned_size_;   // How many bytes we returned last time Next()
-                             // was called (used for error checking only).
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
-};
-
-// ===================================================================
-
-// A ZeroCopyOutputStream which appends bytes to a string.
-class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
- public:
-  // Create a StringOutputStream which appends bytes to the given string.
-  // The string remains property of the caller, but it MUST NOT be accessed
-  // in any way until the stream is destroyed.
-  //
-  // Hint:  If you call target->reserve(n) before creating the stream,
-  //   the first call to Next() will return at least n bytes of buffer
-  //   space.
-  explicit StringOutputStream(string* target);
-  ~StringOutputStream();
-
-  // implements ZeroCopyOutputStream ---------------------------------
-  bool Next(void** data, int* size);
-  void BackUp(int count);
-  int64 ByteCount() const;
-
- private:
-  static const int kMinimumSize = 16;
-
-  string* target_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
-};
-
-// Note:  There is no StringInputStream.  Instead, just create an
-// ArrayInputStream as follows:
-//   ArrayInputStream input(str.data(), str.size());
-
-// ===================================================================
-
-
-// ===================================================================
-
-// A generic traditional input stream interface.
-//
-// Lots of traditional input streams (e.g. file descriptors, C stdio
-// streams, and C++ iostreams) expose an interface where every read
-// involves copying bytes into a buffer.  If you want to take such an
-// interface and make a ZeroCopyInputStream based on it, simply implement
-// CopyingInputStream and then use CopyingInputStreamAdaptor.
-//
-// CopyingInputStream implementations should avoid buffering if possible.
-// CopyingInputStreamAdaptor does its own buffering and will read data
-// in large blocks.
-class LIBPROTOBUF_EXPORT CopyingInputStream {
- public:
-  virtual ~CopyingInputStream();
-
-  // Reads up to "size" bytes into the given buffer.  Returns the number of
-  // bytes read.  Read() waits until at least one byte is available, or
-  // returns zero if no bytes will ever become available (EOF), or -1 if a
-  // permanent read error occurred.
-  virtual int Read(void* buffer, int size) = 0;
-
-  // Skips the next "count" bytes of input.  Returns the number of bytes
-  // actually skipped.  This will always be exactly equal to "count" unless
-  // EOF was reached or a permanent read error occurred.
-  //
-  // The default implementation just repeatedly calls Read() into a scratch
-  // buffer.
-  virtual int Skip(int count);
-};
-
-// A ZeroCopyInputStream which reads from a CopyingInputStream.  This is
-// useful for implementing ZeroCopyInputStreams that read from traditional
-// streams.  Note that this class is not really zero-copy.
-//
-// If you want to read from file descriptors or C++ istreams, this is
-// already implemented for you:  use FileInputStream or IstreamInputStream
-// respectively.
-class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
- public:
-  // Creates a stream that reads from the given CopyingInputStream.
-  // If a block_size is given, it specifies the number of bytes that
-  // should be read and returned with each call to Next().  Otherwise,
-  // a reasonable default is used.  The caller retains ownership of
-  // copying_stream unless SetOwnsCopyingStream(true) is called.
-  explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
-                                     int block_size = -1);
-  ~CopyingInputStreamAdaptor();
-
-  // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
-  // delete the underlying CopyingInputStream when it is destroyed.
-  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
-
-  // implements ZeroCopyInputStream ----------------------------------
-  bool Next(const void** data, int* size);
-  void BackUp(int count);
-  bool Skip(int count);
-  int64 ByteCount() const;
-
- private:
-  // Insures that buffer_ is not NULL.
-  void AllocateBufferIfNeeded();
-  // Frees the buffer and resets buffer_used_.
-  void FreeBuffer();
-
-  // The underlying copying stream.
-  CopyingInputStream* copying_stream_;
-  bool owns_copying_stream_;
-
-  // True if we have seen a permenant error from the underlying stream.
-  bool failed_;
-
-  // The current position of copying_stream_, relative to the point where
-  // we started reading.
-  int64 position_;
-
-  // Data is read into this buffer.  It may be NULL if no buffer is currently
-  // in use.  Otherwise, it points to an array of size buffer_size_.
-  scoped_array<uint8> buffer_;
-  const int buffer_size_;
-
-  // Number of valid bytes currently in the buffer (i.e. the size last
-  // returned by Next()).  0 <= buffer_used_ <= buffer_size_.
-  int buffer_used_;
-
-  // Number of bytes in the buffer which were backed up over by a call to
-  // BackUp().  These need to be returned again.
-  // 0 <= backup_bytes_ <= buffer_used_
-  int backup_bytes_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
-};
-
-// ===================================================================
-
-// A generic traditional output stream interface.
-//
-// Lots of traditional output streams (e.g. file descriptors, C stdio
-// streams, and C++ iostreams) expose an interface where every write
-// involves copying bytes from a buffer.  If you want to take such an
-// interface and make a ZeroCopyOutputStream based on it, simply implement
-// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
-//
-// CopyingOutputStream implementations should avoid buffering if possible.
-// CopyingOutputStreamAdaptor does its own buffering and will write data
-// in large blocks.
-class LIBPROTOBUF_EXPORT CopyingOutputStream {
- public:
-  virtual ~CopyingOutputStream();
-
-  // Writes "size" bytes from the given buffer to the output.  Returns true
-  // if successful, false on a write error.
-  virtual bool Write(const void* buffer, int size) = 0;
-};
-
-// A ZeroCopyOutputStream which writes to a CopyingOutputStream.  This is
-// useful for implementing ZeroCopyOutputStreams that write to traditional
-// streams.  Note that this class is not really zero-copy.
-//
-// If you want to write to file descriptors or C++ ostreams, this is
-// already implemented for you:  use FileOutputStream or OstreamOutputStream
-// respectively.
-class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
- public:
-  // Creates a stream that writes to the given Unix file descriptor.
-  // If a block_size is given, it specifies the size of the buffers
-  // that should be returned by Next().  Otherwise, a reasonable default
-  // is used.
-  explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
-                                      int block_size = -1);
-  ~CopyingOutputStreamAdaptor();
-
-  // Writes all pending data to the underlying stream.  Returns false if a
-  // write error occurred on the underlying stream.  (The underlying
-  // stream itself is not necessarily flushed.)
-  bool Flush();
-
-  // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
-  // delete the underlying CopyingOutputStream when it is destroyed.
-  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
-
-  // implements ZeroCopyOutputStream ---------------------------------
-  bool Next(void** data, int* size);
-  void BackUp(int count);
-  int64 ByteCount() const;
-
- private:
-  // Write the current buffer, if it is present.
-  bool WriteBuffer();
-  // Insures that buffer_ is not NULL.
-  void AllocateBufferIfNeeded();
-  // Frees the buffer.
-  void FreeBuffer();
-
-  // The underlying copying stream.
-  CopyingOutputStream* copying_stream_;
-  bool owns_copying_stream_;
-
-  // True if we have seen a permenant error from the underlying stream.
-  bool failed_;
-
-  // The current position of copying_stream_, relative to the point where
-  // we started writing.
-  int64 position_;
-
-  // Data is written from this buffer.  It may be NULL if no buffer is
-  // currently in use.  Otherwise, it points to an array of size buffer_size_.
-  scoped_array<uint8> buffer_;
-  const int buffer_size_;
-
-  // Number of valid bytes currently in the buffer (i.e. the size last
-  // returned by Next()).  When BackUp() is called, we just reduce this.
-  // 0 <= buffer_used_ <= buffer_size_.
-  int buffer_used_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
-};
 
 // ===================================================================
 
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
new file mode 100644
index 0000000..e801251
--- /dev/null
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -0,0 +1,393 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+namespace {
+
+// Default block size for Copying{In,Out}putStreamAdaptor.
+static const int kDefaultBlockSize = 8192;
+
+}  // namespace
+
+// ===================================================================
+
+ArrayInputStream::ArrayInputStream(const void* data, int size,
+                                   int block_size)
+  : data_(reinterpret_cast<const uint8*>(data)),
+    size_(size),
+    block_size_(block_size > 0 ? block_size : size),
+    position_(0),
+    last_returned_size_(0) {
+}
+
+ArrayInputStream::~ArrayInputStream() {
+}
+
+bool ArrayInputStream::Next(const void** data, int* size) {
+  if (position_ < size_) {
+    last_returned_size_ = min(block_size_, size_ - position_);
+    *data = data_ + position_;
+    *size = last_returned_size_;
+    position_ += last_returned_size_;
+    return true;
+  } else {
+    // We're at the end of the array.
+    last_returned_size_ = 0;   // Don't let caller back up.
+    return false;
+  }
+}
+
+void ArrayInputStream::BackUp(int count) {
+  GOOGLE_CHECK_GT(last_returned_size_, 0)
+      << "BackUp() can only be called after a successful Next().";
+  GOOGLE_CHECK_LE(count, last_returned_size_);
+  GOOGLE_CHECK_GE(count, 0);
+  position_ -= count;
+  last_returned_size_ = 0;  // Don't let caller back up further.
+}
+
+bool ArrayInputStream::Skip(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+  last_returned_size_ = 0;   // Don't let caller back up.
+  if (count > size_ - position_) {
+    position_ = size_;
+    return false;
+  } else {
+    position_ += count;
+    return true;
+  }
+}
+
+int64 ArrayInputStream::ByteCount() const {
+  return position_;
+}
+
+
+// ===================================================================
+
+ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
+  : data_(reinterpret_cast<uint8*>(data)),
+    size_(size),
+    block_size_(block_size > 0 ? block_size : size),
+    position_(0),
+    last_returned_size_(0) {
+}
+
+ArrayOutputStream::~ArrayOutputStream() {
+}
+
+bool ArrayOutputStream::Next(void** data, int* size) {
+  if (position_ < size_) {
+    last_returned_size_ = min(block_size_, size_ - position_);
+    *data = data_ + position_;
+    *size = last_returned_size_;
+    position_ += last_returned_size_;
+    return true;
+  } else {
+    // We're at the end of the array.
+    last_returned_size_ = 0;   // Don't let caller back up.
+    return false;
+  }
+}
+
+void ArrayOutputStream::BackUp(int count) {
+  GOOGLE_CHECK_GT(last_returned_size_, 0)
+      << "BackUp() can only be called after a successful Next().";
+  GOOGLE_CHECK_LE(count, last_returned_size_);
+  GOOGLE_CHECK_GE(count, 0);
+  position_ -= count;
+  last_returned_size_ = 0;  // Don't let caller back up further.
+}
+
+int64 ArrayOutputStream::ByteCount() const {
+  return position_;
+}
+
+// ===================================================================
+
+StringOutputStream::StringOutputStream(string* target)
+  : target_(target) {
+}
+
+StringOutputStream::~StringOutputStream() {
+}
+
+bool StringOutputStream::Next(void** data, int* size) {
+  int old_size = target_->size();
+
+  // Grow the string.
+  if (old_size < target_->capacity()) {
+    // Resize the string to match its capacity, since we can get away
+    // without a memory allocation this way.
+    STLStringResizeUninitialized(target_, target_->capacity());
+  } else {
+    // Size has reached capacity, so double the size.  Also make sure
+    // that the new size is at least kMinimumSize.
+    STLStringResizeUninitialized(
+      target_,
+      max(old_size * 2,
+          kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
+  }
+
+  *data = string_as_array(target_) + old_size;
+  *size = target_->size() - old_size;
+  return true;
+}
+
+void StringOutputStream::BackUp(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+  GOOGLE_CHECK_LE(count, target_->size());
+  target_->resize(target_->size() - count);
+}
+
+int64 StringOutputStream::ByteCount() const {
+  return target_->size();
+}
+
+// ===================================================================
+
+CopyingInputStream::~CopyingInputStream() {}
+
+int CopyingInputStream::Skip(int count) {
+  char junk[4096];
+  int skipped = 0;
+  while (skipped < count) {
+    int bytes = Read(junk, min(count - skipped,
+                               implicit_cast<int>(sizeof(junk))));
+    if (bytes <= 0) {
+      // EOF or read error.
+      return skipped;
+    }
+    skipped += bytes;
+  }
+  return skipped;
+}
+
+CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
+    CopyingInputStream* copying_stream, int block_size)
+  : copying_stream_(copying_stream),
+    owns_copying_stream_(false),
+    failed_(false),
+    position_(0),
+    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
+    buffer_used_(0),
+    backup_bytes_(0) {
+}
+
+CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
+  if (owns_copying_stream_) {
+    delete copying_stream_;
+  }
+}
+
+bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
+  if (failed_) {
+    // Already failed on a previous read.
+    return false;
+  }
+
+  AllocateBufferIfNeeded();
+
+  if (backup_bytes_ > 0) {
+    // We have data left over from a previous BackUp(), so just return that.
+    *data = buffer_.get() + buffer_used_ - backup_bytes_;
+    *size = backup_bytes_;
+    backup_bytes_ = 0;
+    return true;
+  }
+
+  // Read new data into the buffer.
+  buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
+  if (buffer_used_ <= 0) {
+    // EOF or read error.  We don't need the buffer anymore.
+    if (buffer_used_ < 0) {
+      // Read error (not EOF).
+      failed_ = true;
+    }
+    FreeBuffer();
+    return false;
+  }
+  position_ += buffer_used_;
+
+  *size = buffer_used_;
+  *data = buffer_.get();
+  return true;
+}
+
+void CopyingInputStreamAdaptor::BackUp(int count) {
+  GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
+    << " BackUp() can only be called after Next().";
+  GOOGLE_CHECK_LE(count, buffer_used_)
+    << " Can't back up over more bytes than were returned by the last call"
+       " to Next().";
+  GOOGLE_CHECK_GE(count, 0)
+    << " Parameter to BackUp() can't be negative.";
+
+  backup_bytes_ = count;
+}
+
+bool CopyingInputStreamAdaptor::Skip(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+
+  if (failed_) {
+    // Already failed on a previous read.
+    return false;
+  }
+
+  // First skip any bytes left over from a previous BackUp().
+  if (backup_bytes_ >= count) {
+    // We have more data left over than we're trying to skip.  Just chop it.
+    backup_bytes_ -= count;
+    return true;
+  }
+
+  count -= backup_bytes_;
+  backup_bytes_ = 0;
+
+  int skipped = copying_stream_->Skip(count);
+  position_ += skipped;
+  return skipped == count;
+}
+
+int64 CopyingInputStreamAdaptor::ByteCount() const {
+  return position_ - backup_bytes_;
+}
+
+void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
+  if (buffer_.get() == NULL) {
+    buffer_.reset(new uint8[buffer_size_]);
+  }
+}
+
+void CopyingInputStreamAdaptor::FreeBuffer() {
+  GOOGLE_CHECK_EQ(backup_bytes_, 0);
+  buffer_used_ = 0;
+  buffer_.reset();
+}
+
+// ===================================================================
+
+CopyingOutputStream::~CopyingOutputStream() {}
+
+CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
+    CopyingOutputStream* copying_stream, int block_size)
+  : copying_stream_(copying_stream),
+    owns_copying_stream_(false),
+    failed_(false),
+    position_(0),
+    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
+    buffer_used_(0) {
+}
+
+CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
+  WriteBuffer();
+  if (owns_copying_stream_) {
+    delete copying_stream_;
+  }
+}
+
+bool CopyingOutputStreamAdaptor::Flush() {
+  return WriteBuffer();
+}
+
+bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
+  if (buffer_used_ == buffer_size_) {
+    if (!WriteBuffer()) return false;
+  }
+
+  AllocateBufferIfNeeded();
+
+  *data = buffer_.get() + buffer_used_;
+  *size = buffer_size_ - buffer_used_;
+  buffer_used_ = buffer_size_;
+  return true;
+}
+
+void CopyingOutputStreamAdaptor::BackUp(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+  GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
+    << " BackUp() can only be called after Next().";
+  GOOGLE_CHECK_LE(count, buffer_used_)
+    << " Can't back up over more bytes than were returned by the last call"
+       " to Next().";
+
+  buffer_used_ -= count;
+}
+
+int64 CopyingOutputStreamAdaptor::ByteCount() const {
+  return position_ + buffer_used_;
+}
+
+bool CopyingOutputStreamAdaptor::WriteBuffer() {
+  if (failed_) {
+    // Already failed on a previous write.
+    return false;
+  }
+
+  if (buffer_used_ == 0) return true;
+
+  if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
+    position_ += buffer_used_;
+    buffer_used_ = 0;
+    return true;
+  } else {
+    failed_ = true;
+    FreeBuffer();
+    return false;
+  }
+}
+
+void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
+  if (buffer_ == NULL) {
+    buffer_.reset(new uint8[buffer_size_]);
+  }
+}
+
+void CopyingOutputStreamAdaptor::FreeBuffer() {
+  buffer_used_ = 0;
+  buffer_.reset();
+}
+
+// ===================================================================
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
new file mode 100644
index 0000000..59f1825
--- /dev/null
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -0,0 +1,338 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains common implementations of the interfaces defined in
+// zero_copy_stream.h.  These implementations cover I/O on raw arrays,
+// strings, and file descriptors.  Of course, many users will probably
+// want to write their own implementations of these interfaces specific
+// to the particular I/O abstractions they prefer to use, but these
+// should cover the most common cases.
+
+#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
+#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
+
+#include <string>
+#include <iosfwd>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/common.h>
+
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+// ===================================================================
+
+// A ZeroCopyInputStream backed by an in-memory array of bytes.
+class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
+ public:
+  // Create an InputStream that returns the bytes pointed to by "data".
+  // "data" remains the property of the caller but must remain valid until
+  // the stream is destroyed.  If a block_size is given, calls to Next()
+  // will return data blocks no larger than the given size.  Otherwise, the
+  // first call to Next() returns the entire array.  block_size is mainly
+  // useful for testing; in production you would probably never want to set
+  // it.
+  ArrayInputStream(const void* data, int size, int block_size = -1);
+  ~ArrayInputStream();
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+
+ private:
+  const uint8* const data_;  // The byte array.
+  const int size_;           // Total size of the array.
+  const int block_size_;     // How many bytes to return at a time.
+
+  int position_;
+  int last_returned_size_;   // How many bytes we returned last time Next()
+                             // was called (used for error checking only).
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyOutputStream backed by an in-memory array of bytes.
+class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Create an OutputStream that writes to the bytes pointed to by "data".
+  // "data" remains the property of the caller but must remain valid until
+  // the stream is destroyed.  If a block_size is given, calls to Next()
+  // will return data blocks no larger than the given size.  Otherwise, the
+  // first call to Next() returns the entire array.  block_size is mainly
+  // useful for testing; in production you would probably never want to set
+  // it.
+  ArrayOutputStream(void* data, int size, int block_size = -1);
+  ~ArrayOutputStream();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  uint8* const data_;        // The byte array.
+  const int size_;           // Total size of the array.
+  const int block_size_;     // How many bytes to return at a time.
+
+  int position_;
+  int last_returned_size_;   // How many bytes we returned last time Next()
+                             // was called (used for error checking only).
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyOutputStream which appends bytes to a string.
+class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Create a StringOutputStream which appends bytes to the given string.
+  // The string remains property of the caller, but it MUST NOT be accessed
+  // in any way until the stream is destroyed.
+  //
+  // Hint:  If you call target->reserve(n) before creating the stream,
+  //   the first call to Next() will return at least n bytes of buffer
+  //   space.
+  explicit StringOutputStream(string* target);
+  ~StringOutputStream();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  static const int kMinimumSize = 16;
+
+  string* target_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
+};
+
+// Note:  There is no StringInputStream.  Instead, just create an
+// ArrayInputStream as follows:
+//   ArrayInputStream input(str.data(), str.size());
+
+// ===================================================================
+
+// A generic traditional input stream interface.
+//
+// Lots of traditional input streams (e.g. file descriptors, C stdio
+// streams, and C++ iostreams) expose an interface where every read
+// involves copying bytes into a buffer.  If you want to take such an
+// interface and make a ZeroCopyInputStream based on it, simply implement
+// CopyingInputStream and then use CopyingInputStreamAdaptor.
+//
+// CopyingInputStream implementations should avoid buffering if possible.
+// CopyingInputStreamAdaptor does its own buffering and will read data
+// in large blocks.
+class LIBPROTOBUF_EXPORT CopyingInputStream {
+ public:
+  virtual ~CopyingInputStream();
+
+  // Reads up to "size" bytes into the given buffer.  Returns the number of
+  // bytes read.  Read() waits until at least one byte is available, or
+  // returns zero if no bytes will ever become available (EOF), or -1 if a
+  // permanent read error occurred.
+  virtual int Read(void* buffer, int size) = 0;
+
+  // Skips the next "count" bytes of input.  Returns the number of bytes
+  // actually skipped.  This will always be exactly equal to "count" unless
+  // EOF was reached or a permanent read error occurred.
+  //
+  // The default implementation just repeatedly calls Read() into a scratch
+  // buffer.
+  virtual int Skip(int count);
+};
+
+// A ZeroCopyInputStream which reads from a CopyingInputStream.  This is
+// useful for implementing ZeroCopyInputStreams that read from traditional
+// streams.  Note that this class is not really zero-copy.
+//
+// If you want to read from file descriptors or C++ istreams, this is
+// already implemented for you:  use FileInputStream or IstreamInputStream
+// respectively.
+class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
+ public:
+  // Creates a stream that reads from the given CopyingInputStream.
+  // If a block_size is given, it specifies the number of bytes that
+  // should be read and returned with each call to Next().  Otherwise,
+  // a reasonable default is used.  The caller retains ownership of
+  // copying_stream unless SetOwnsCopyingStream(true) is called.
+  explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
+                                     int block_size = -1);
+  ~CopyingInputStreamAdaptor();
+
+  // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
+  // delete the underlying CopyingInputStream when it is destroyed.
+  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+ private:
+  // Insures that buffer_ is not NULL.
+  void AllocateBufferIfNeeded();
+  // Frees the buffer and resets buffer_used_.
+  void FreeBuffer();
+
+  // The underlying copying stream.
+  CopyingInputStream* copying_stream_;
+  bool owns_copying_stream_;
+
+  // True if we have seen a permenant error from the underlying stream.
+  bool failed_;
+
+  // The current position of copying_stream_, relative to the point where
+  // we started reading.
+  int64 position_;
+
+  // Data is read into this buffer.  It may be NULL if no buffer is currently
+  // in use.  Otherwise, it points to an array of size buffer_size_.
+  scoped_array<uint8> buffer_;
+  const int buffer_size_;
+
+  // Number of valid bytes currently in the buffer (i.e. the size last
+  // returned by Next()).  0 <= buffer_used_ <= buffer_size_.
+  int buffer_used_;
+
+  // Number of bytes in the buffer which were backed up over by a call to
+  // BackUp().  These need to be returned again.
+  // 0 <= backup_bytes_ <= buffer_used_
+  int backup_bytes_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
+};
+
+// ===================================================================
+
+// A generic traditional output stream interface.
+//
+// Lots of traditional output streams (e.g. file descriptors, C stdio
+// streams, and C++ iostreams) expose an interface where every write
+// involves copying bytes from a buffer.  If you want to take such an
+// interface and make a ZeroCopyOutputStream based on it, simply implement
+// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
+//
+// CopyingOutputStream implementations should avoid buffering if possible.
+// CopyingOutputStreamAdaptor does its own buffering and will write data
+// in large blocks.
+class LIBPROTOBUF_EXPORT CopyingOutputStream {
+ public:
+  virtual ~CopyingOutputStream();
+
+  // Writes "size" bytes from the given buffer to the output.  Returns true
+  // if successful, false on a write error.
+  virtual bool Write(const void* buffer, int size) = 0;
+};
+
+// A ZeroCopyOutputStream which writes to a CopyingOutputStream.  This is
+// useful for implementing ZeroCopyOutputStreams that write to traditional
+// streams.  Note that this class is not really zero-copy.
+//
+// If you want to write to file descriptors or C++ ostreams, this is
+// already implemented for you:  use FileOutputStream or OstreamOutputStream
+// respectively.
+class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
+ public:
+  // Creates a stream that writes to the given Unix file descriptor.
+  // If a block_size is given, it specifies the size of the buffers
+  // that should be returned by Next().  Otherwise, a reasonable default
+  // is used.
+  explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
+                                      int block_size = -1);
+  ~CopyingOutputStreamAdaptor();
+
+  // Writes all pending data to the underlying stream.  Returns false if a
+  // write error occurred on the underlying stream.  (The underlying
+  // stream itself is not necessarily flushed.)
+  bool Flush();
+
+  // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
+  // delete the underlying CopyingOutputStream when it is destroyed.
+  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  // Write the current buffer, if it is present.
+  bool WriteBuffer();
+  // Insures that buffer_ is not NULL.
+  void AllocateBufferIfNeeded();
+  // Frees the buffer.
+  void FreeBuffer();
+
+  // The underlying copying stream.
+  CopyingOutputStream* copying_stream_;
+  bool owns_copying_stream_;
+
+  // True if we have seen a permenant error from the underlying stream.
+  bool failed_;
+
+  // The current position of copying_stream_, relative to the point where
+  // we started writing.
+  int64 position_;
+
+  // Data is written from this buffer.  It may be NULL if no buffer is
+  // currently in use.  Otherwise, it points to an array of size buffer_size_.
+  scoped_array<uint8> buffer_;
+  const int buffer_size_;
+
+  // Number of valid bytes currently in the buffer (i.e. the size last
+  // returned by Next()).  When BackUp() is called, we just reduce this.
+  // 0 <= buffer_used_ <= buffer_size_.
+  int buffer_used_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
+};
+
+// ===================================================================
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 9adef74..5e3310a 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -61,6 +61,7 @@
 #include <sstream>
 
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+
 #if HAVE_ZLIB
 #include <google/protobuf/io/gzip_stream.h>
 #endif
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
new file mode 100644
index 0000000..8393285
--- /dev/null
+++ b/src/google/protobuf/lite_unittest.cc
@@ -0,0 +1,112 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <string>
+#include <iostream>
+
+#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/stubs/common.h>
+
+using namespace std;
+
+int main(int argc, char* argv[]) {
+  string data, packed_data;
+
+  {
+    protobuf_unittest::TestAllTypesLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectClear(message);
+    google::protobuf::TestUtilLite::SetAllFields(&message);
+    message2.CopyFrom(message);
+    data = message.SerializeAsString();
+    message3.ParseFromString(data);
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message);
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2);
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message3);
+    google::protobuf::TestUtilLite::ModifyRepeatedFields(&message);
+    google::protobuf::TestUtilLite::ExpectRepeatedFieldsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectClear(message);
+  }
+
+  {
+    protobuf_unittest::TestAllExtensionsLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
+    google::protobuf::TestUtilLite::SetAllExtensions(&message);
+    message2.CopyFrom(message);
+    string extensions_data = message.SerializeAsString();
+    GOOGLE_CHECK(extensions_data == data);
+    message3.ParseFromString(extensions_data);
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message);
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2);
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message3);
+    google::protobuf::TestUtilLite::ModifyRepeatedExtensions(&message);
+    google::protobuf::TestUtilLite::ExpectRepeatedExtensionsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
+  }
+
+  {
+    protobuf_unittest::TestPackedTypesLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectPackedClear(message);
+    google::protobuf::TestUtilLite::SetPackedFields(&message);
+    message2.CopyFrom(message);
+    packed_data = message.SerializeAsString();
+    message3.ParseFromString(packed_data);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message3);
+    google::protobuf::TestUtilLite::ModifyPackedFields(&message);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectPackedClear(message);
+  }
+
+  {
+    protobuf_unittest::TestPackedExtensionsLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
+    google::protobuf::TestUtilLite::SetPackedExtensions(&message);
+    message2.CopyFrom(message);
+    string packed_extensions_data = message.SerializeAsString();
+    GOOGLE_CHECK(packed_extensions_data == packed_data);
+    message3.ParseFromString(packed_extensions_data);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message3);
+    google::protobuf::TestUtilLite::ModifyPackedExtensions(&message);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
+  }
+
+  cout << "PASS";
+  return 0;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 9df3d39..f4519cd 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -45,7 +45,6 @@
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map-util.h>
 #include <google/protobuf/stubs/stl_util-inl.h>
 
@@ -55,15 +54,6 @@
 using internal::WireFormat;
 using internal::ReflectionOps;
 
-static string InitializationErrorMessage(const char* action,
-                                         const Message& message) {
-  return strings::Substitute(
-    "Can't $0 message of type \"$1\" because it is missing required "
-    "fields: $2",
-    action, message.GetDescriptor()->full_name(),
-    message.InitializationErrorString());
-}
-
 Message::~Message() {}
 
 void Message::MergeFrom(const Message& from) {
@@ -75,6 +65,10 @@
   ReflectionOps::Merge(from, this);
 }
 
+void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
+  MergeFrom(*down_cast<const Message*>(&other));
+}
+
 void Message::CopyFrom(const Message& from) {
   const Descriptor* descriptor = GetDescriptor();
   GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
@@ -84,6 +78,10 @@
   ReflectionOps::Copy(from, this);
 }
 
+string Message::GetTypeName() const {
+  return GetDescriptor()->full_name();
+}
+
 void Message::Clear() {
   ReflectionOps::Clear(this);
 }
@@ -116,74 +114,6 @@
   return WireFormat::ParseAndMergePartial(input, this);
 }
 
-bool Message::MergeFromCodedStream(io::CodedInputStream* input) {
-  if (!MergePartialFromCodedStream(input)) return false;
-  if (!IsInitialized()) {
-    GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *this);
-    return false;
-  }
-  return true;
-}
-
-bool Message::ParseFromCodedStream(io::CodedInputStream* input) {
-  Clear();
-  return MergeFromCodedStream(input);
-}
-
-bool Message::ParsePartialFromCodedStream(io::CodedInputStream* input) {
-  Clear();
-  return MergePartialFromCodedStream(input);
-}
-
-bool Message::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
-  io::CodedInputStream decoder(input);
-  return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
-}
-
-bool Message::ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input) {
-  io::CodedInputStream decoder(input);
-  return ParsePartialFromCodedStream(&decoder) &&
-         decoder.ConsumedEntireMessage();
-}
-
-bool Message::ParseFromBoundedZeroCopyStream(
-    io::ZeroCopyInputStream* input, int size) {
-  io::CodedInputStream decoder(input);
-  decoder.PushLimit(size);
-  return ParseFromCodedStream(&decoder) &&
-         decoder.ConsumedEntireMessage() &&
-         decoder.BytesUntilLimit() == 0;
-}
-
-bool Message::ParsePartialFromBoundedZeroCopyStream(
-    io::ZeroCopyInputStream* input, int size) {
-  io::CodedInputStream decoder(input);
-  decoder.PushLimit(size);
-  return ParsePartialFromCodedStream(&decoder) &&
-         decoder.ConsumedEntireMessage() &&
-         decoder.BytesUntilLimit() == 0;
-}
-
-bool Message::ParseFromString(const string& data) {
-  io::ArrayInputStream input(data.data(), data.size());
-  return ParseFromBoundedZeroCopyStream(&input, data.size());
-}
-
-bool Message::ParsePartialFromString(const string& data) {
-  io::ArrayInputStream input(data.data(), data.size());
-  return ParsePartialFromBoundedZeroCopyStream(&input, data.size());
-}
-
-bool Message::ParseFromArray(const void* data, int size) {
-  io::ArrayInputStream input(data, size);
-  return ParseFromBoundedZeroCopyStream(&input, size);
-}
-
-bool Message::ParsePartialFromArray(const void* data, int size) {
-  io::ArrayInputStream input(data, size);
-  return ParsePartialFromBoundedZeroCopyStream(&input, size);
-}
-
 bool Message::ParseFromFileDescriptor(int file_descriptor) {
   io::FileInputStream input(file_descriptor);
   return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
@@ -205,22 +135,11 @@
 }
 
 
-
 void Message::SerializeWithCachedSizes(
     io::CodedOutputStream* output) const {
   WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
 }
 
-uint8* Message::SerializeWithCachedSizesToArray(uint8* target) const {
-  // We only optimize this when using optimize_for = SPEED.
-  int size = GetCachedSize();
-  io::ArrayOutputStream out(target, size);
-  io::CodedOutputStream coded_out(&out);
-  SerializeWithCachedSizes(&coded_out);
-  GOOGLE_CHECK(!coded_out.HadError());
-  return target + size;
-}
-
 int Message::ByteSize() const {
   int size = WireFormat::ByteSize(*this);
   SetCachedSize(size);
@@ -237,69 +156,6 @@
   return GetReflection()->SpaceUsed(*this);
 }
 
-bool Message::SerializeToCodedStream(io::CodedOutputStream* output) const {
-  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
-  return SerializePartialToCodedStream(output);
-}
-
-bool Message::SerializePartialToCodedStream(
-    io::CodedOutputStream* output) const {
-  ByteSize();  // Force size to be cached.
-  SerializeWithCachedSizes(output);
-  return !output->HadError();
-}
-
-bool Message::SerializeToZeroCopyStream(
-    io::ZeroCopyOutputStream* output) const {
-  io::CodedOutputStream encoder(output);
-  return SerializeToCodedStream(&encoder);
-}
-
-bool Message::SerializePartialToZeroCopyStream(
-    io::ZeroCopyOutputStream* output) const {
-  io::CodedOutputStream encoder(output);
-  return SerializePartialToCodedStream(&encoder);
-}
-
-bool Message::AppendToString(string* output) const {
-  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
-  return AppendPartialToString(output);
-}
-
-bool Message::AppendPartialToString(string* output) const {
-  int old_size = output->size();
-  int byte_size = ByteSize();
-  STLStringResizeUninitialized(output, old_size + byte_size);
-  uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size);
-  uint8* end = SerializeWithCachedSizesToArray(start);
-  GOOGLE_CHECK_EQ(end, start + byte_size);
-  return true;
-}
-
-bool Message::SerializeToString(string* output) const {
-  output->clear();
-  return AppendToString(output);
-}
-
-bool Message::SerializePartialToString(string* output) const {
-  output->clear();
-  return AppendPartialToString(output);
-}
-
-bool Message::SerializeToArray(void* data, int size) const {
-  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
-  return SerializePartialToArray(data, size);
-}
-
-bool Message::SerializePartialToArray(void* data, int size) const {
-  int byte_size = ByteSize();
-  if (size < byte_size) return false;
-  uint8* end =
-    SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(data));
-  GOOGLE_CHECK_EQ(end, reinterpret_cast<uint8*>(data) + byte_size);
-  return true;
-}
-
 bool Message::SerializeToFileDescriptor(int file_descriptor) const {
   io::FileOutputStream output(file_descriptor);
   return SerializeToZeroCopyStream(&output);
@@ -321,24 +177,6 @@
 }
 
 
-string Message::SerializeAsString() const {
-  // If the compiler implements the (Named) Return Value Optimization,
-  // the local variable 'result' will not actually reside on the stack
-  // of this function, but will be overlaid with the object that the
-  // caller supplied for the return value to be constructed in.
-  string output;
-  if (!AppendToString(&output))
-    output.clear();
-  return output;
-}
-
-string Message::SerializePartialAsString() const {
-  string output;
-  if (!AppendPartialToString(&output))
-    output.clear();
-  return output;
-}
-
 Reflection::~Reflection() {}
 
 // ===================================================================
@@ -355,7 +193,7 @@
 
   static GeneratedMessageFactory* singleton();
 
-  typedef void RegistrationFunc();
+  typedef void RegistrationFunc(const string&);
   void RegisterFile(const char* file, RegistrationFunc* registration_func);
   void RegisterType(const Descriptor* descriptor, const Message* prototype);
 
@@ -378,8 +216,8 @@
 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
   // No need for thread-safety here because this will be called at static
   // initialization time.  (And GCC4 makes this thread-safe anyway.)
-  static GeneratedMessageFactory singleton;
-  return &singleton;
+  static GeneratedMessageFactory* singleton = new GeneratedMessageFactory;
+  return singleton;
 }
 
 void GeneratedMessageFactory::RegisterFile(
@@ -430,7 +268,7 @@
   const Message* result = FindPtrOrNull(type_map_, type);
   if (result == NULL) {
     // Nope.  OK, register everything.
-    registration_func();
+    registration_func(type->file()->name());
     // Should be here now.
     result = FindPtrOrNull(type_map_, type);
   }
@@ -450,7 +288,7 @@
 }
 
 void MessageFactory::InternalRegisterGeneratedFile(
-    const char* filename, void (*register_messages)()) {
+    const char* filename, void (*register_messages)(const string&)) {
   GeneratedMessageFactory::singleton()->RegisterFile(filename,
                                                      register_messages);
 }
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 4171605..eecd91a 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -98,9 +98,9 @@
 //     const Reflection* reflection = foo->GetReflection();
 //     assert(reflection->GetString(foo, text_field) == "Hello World!");
 //     assert(reflection->FieldSize(foo, numbers_field) == 3);
-//     assert(reflection->GetInt32(foo, numbers_field, 0) == 1);
-//     assert(reflection->GetInt32(foo, numbers_field, 1) == 5);
-//     assert(reflection->GetInt32(foo, numbers_field, 2) == 42);
+//     assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1);
+//     assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5);
+//     assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42);
 //
 //     delete foo;
 //   }
@@ -118,6 +118,10 @@
 #include <iosfwd>
 #endif
 
+#include <google/protobuf/message_lite.h>
+
+#include <google/protobuf/stubs/common.h>
+
 #if defined(_WIN32) && defined(GetMessage)
 // windows.h defines GetMessage() as a macro.  Let's re-define it as an inline
 // function.  This is necessary because Reflection has a method called
@@ -136,10 +140,8 @@
 }
 #endif
 
-#include <google/protobuf/stubs/common.h>
 
 namespace google {
-
 namespace protobuf {
 
 // Defined in this file.
@@ -149,6 +151,7 @@
 // Defined in other files.
 class Descriptor;            // descriptor.h
 class FieldDescriptor;       // descriptor.h
+class EnumDescriptor;        // descriptor.h
 class EnumValueDescriptor;   // descriptor.h
 namespace io {
   class ZeroCopyInputStream;   // zero_copy_stream.h
@@ -158,14 +161,28 @@
 }
 class UnknownFieldSet;       // unknown_field_set.h
 
+// A container to hold message metadata.
+struct Metadata {
+  const Descriptor* descriptor;
+  const Reflection* reflection;
+};
+
+// Returns the EnumDescriptor for enum type E, which must be a
+// proto-declared enum type.
+template <typename E>
+const EnumDescriptor* GetEnumDescriptor();
+
 // Abstract interface for protocol messages.
 //
+// See also MessageLite, which contains most every-day operations.  Message
+// adds descriptors and reflection on top of that.
+//
 // The methods of this class that are virtual but not pure-virtual have
 // default implementations based on reflection.  Message classes which are
 // optimized for speed will want to override these with faster implementations,
 // but classes optimized for code size may be happy with keeping them.  See
 // the optimize_for option in descriptor.proto.
-class LIBPROTOBUF_EXPORT Message {
+class LIBPROTOBUF_EXPORT Message : public MessageLite {
  public:
   inline Message() {}
   virtual ~Message();
@@ -173,7 +190,8 @@
   // Basic Operations ------------------------------------------------
 
   // Construct a new instance of the same type.  Ownership is passed to the
-  // caller.
+  // caller.  (This is also defined in MessageLite, but is defined again here
+  // for return-type covariance.)
   virtual Message* New() const = 0;
 
   // Make this message into a copy of the given message.  The given message
@@ -187,16 +205,6 @@
   // must be of the same type as this message (i.e. the exact same class).
   virtual void MergeFrom(const Message& from);
 
-  // Clear all fields of the message and set them to their default values.
-  // Clear() avoids freeing memory, assuming that any memory allocated
-  // to hold parts of the message will be needed again to hold the next
-  // message.  If you actually want to free the memory used by a Message,
-  // you must delete it.
-  virtual void Clear();
-
-  // Quickly check if all required fields have values set.
-  virtual bool IsInitialized() const;
-
   // Verifies that IsInitialized() returns true.  GOOGLE_CHECK-fails otherwise, with
   // a nice error message.
   void CheckInitialized() const;
@@ -238,41 +246,9 @@
   // Convenience function useful in GDB.  Prints DebugString() to stdout.
   void PrintDebugString() const;
 
-  // Parsing ---------------------------------------------------------
-  // Methods for parsing in protocol buffer format.  Most of these are
-  // just simple wrappers around MergeFromCodedStream().
-
-  // 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.
-  bool ParseFromCodedStream(io::CodedInputStream* input);
-  // Like ParseFromCodedStream(), but accepts messages that are missing
-  // required fields.
-  bool ParsePartialFromCodedStream(io::CodedInputStream* input);
-  // Read a protocol buffer from the given zero-copy input stream.  If
-  // successful, the entire input will be consumed.
-  bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
-  // Like ParseFromZeroCopyStream(), but accepts messages that are missing
-  // required fields.
-  bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
-  // Read a protocol buffer from the given zero-copy input stream, expecting
-  // the message to be exactly "size" bytes long.  If successful, exactly
-  // this many bytes will have been consumed from the input.
-  bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
-  // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
-  // missing required fields.
-  bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
-                                             int size);
-  // Parse a protocol buffer contained in a string.
-  bool ParseFromString(const string& data);
-  // Like ParseFromString(), but accepts messages that are missing
-  // required fields.
-  bool ParsePartialFromString(const string& data);
-  // Parse a protocol buffer contained in an array of bytes.
-  bool ParseFromArray(const void* data, int size);
-  // Like ParseFromArray(), but accepts messages that are missing
-  // required fields.
-  bool ParsePartialFromArray(const void* data, int size);
+  // Heavy I/O -------------------------------------------------------
+  // Additional parsing and serialization methods not implemented by
+  // MessageLite because they are not supported by the lite library.
 
   // Parse a protocol buffer from a file descriptor.  If successful, the entire
   // input will be consumed.
@@ -287,53 +263,6 @@
   // required fields.
   bool ParsePartialFromIstream(istream* input);
 
-
-  // Reads a protocol buffer from the stream and merges it into this
-  // Message.  Singular fields read from the input overwrite what is
-  // already in the Message and repeated fields are appended to those
-  // already present.
-  //
-  // It is the responsibility of the caller to call input->LastTagWas()
-  // (for groups) or input->ConsumedEntireMessage() (for non-groups) after
-  // this returns to verify that the message's end was delimited correctly.
-  //
-  // ParsefromCodedStream() is implemented as Clear() followed by
-  // MergeFromCodedStream().
-  bool MergeFromCodedStream(io::CodedInputStream* input);
-
-  // Like MergeFromCodedStream(), but succeeds even if required fields are
-  // missing in the input.
-  //
-  // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
-  // followed by IsInitialized().
-  virtual bool MergePartialFromCodedStream(io::CodedInputStream* input);
-
-  // Serialization ---------------------------------------------------
-  // Methods for serializing in protocol buffer format.  Most of these
-  // are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
-
-  // Write a protocol buffer of this message to the given output.  Returns
-  // false on a write error.  If the message is missing required fields,
-  // this may GOOGLE_CHECK-fail.
-  bool SerializeToCodedStream(io::CodedOutputStream* output) const;
-  // Like SerializeToCodedStream(), but allows missing required fields.
-  bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
-  // Write the message to the given zero-copy output stream.  All required
-  // fields must be set.
-  bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
-  // Like SerializeToZeroCopyStream(), but allows missing required fields.
-  bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
-  // Serialize the message and store it in the given string.  All required
-  // fields must be set.
-  bool SerializeToString(string* output) const;
-  // Like SerializeToString(), but allows missing required fields.
-  bool SerializePartialToString(string* output) const;
-  // Serialize the message and store it in the given byte array.  All required
-  // fields must be set.
-  bool SerializeToArray(void* data, int size) const;
-  // Like SerializeToArray(), but allows missing required fields.
-  bool SerializePartialToArray(void* data, int size) const;
-
   // Serialize the message and write it to the given file descriptor.  All
   // required fields must be set.
   bool SerializeToFileDescriptor(int file_descriptor) const;
@@ -346,50 +275,18 @@
   bool SerializePartialToOstream(ostream* output) const;
 
 
-  // Make a string encoding the message. Is equivalent to calling
-  // SerializeToString() on a string and using that.  Returns the empty
-  // string if SerializeToString() would have returned an error.
-  // Note: If you intend to generate many such strings, you may
-  // reduce heap fragmentation by instead re-using the same string
-  // object with calls to SerializeToString().
-  string SerializeAsString() const;
-  // Like SerializeAsString(), but allows missing required fields.
-  string SerializePartialAsString() const;
+  // Reflection-based methods ----------------------------------------
+  // These methods are pure-virtual in MessageLite, but Message provides
+  // reflection-based default implementations.
 
-  // Like SerializeToString(), but appends to the data to the string's existing
-  // contents.  All required fields must be set.
-  bool AppendToString(string* output) const;
-  // Like AppendToString(), but allows missing required fields.
-  bool AppendPartialToString(string* output) const;
-
-  // Computes the serialized size of the message.  This recursively calls
-  // ByteSize() on all embedded messages.  If a subclass does not override
-  // this, it MUST override SetCachedSize().
+  virtual string GetTypeName() const;
+  virtual void Clear();
+  virtual bool IsInitialized() const;
+  virtual void CheckTypeAndMergeFrom(const MessageLite& other);
+  virtual bool MergePartialFromCodedStream(io::CodedInputStream* input);
   virtual int ByteSize() const;
-
-  // Serializes the message without recomputing the size.  The message must
-  // not have changed since the last call to ByteSize(); if it has, the results
-  // are undefined.
   virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const;
 
-  // Like SerializeWithCachedSizes, but writes directly to *target, returning
-  // a pointer to the byte immediately after the last byte written.  "target"
-  // must point at a byte array of at least ByteSize() bytes.
-  virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const;
-
-  // Returns the result of the last call to ByteSize().  An embedded message's
-  // size is needed both to serialize it (because embedded messages are
-  // length-delimited) and to compute the outer message's size.  Caching
-  // the size avoids computing it multiple times.
-  //
-  // ByteSize() does not automatically use the cached size when available
-  // because this would require invalidating it every time the message was
-  // modified, which would be too hard and expensive.  (E.g. if a deeply-nested
-  // sub-message is changed, all of its parents' cached sizes would need to be
-  // invalidated, which is too much work for an otherwise inlined setter
-  // method.)
-  virtual int GetCachedSize() const = 0;
-
  private:
   // This is called only by the default implementation of ByteSize(), to
   // update the cached size.  If you override ByteSize(), you do not need
@@ -409,13 +306,24 @@
 
   // Get a Descriptor for this message's type.  This describes what
   // fields the message contains, the types of those fields, etc.
-  virtual const Descriptor* GetDescriptor() const = 0;
+  const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; }
 
   // Get the Reflection interface for this Message, which can be used to
   // read and modify the fields of the Message dynamically (in other words,
   // without knowing the message type at compile time).  This object remains
   // property of the Message.
-  virtual const Reflection* GetReflection() const = 0;
+  //
+  // This method remains virtual in case a subclass does not implement
+  // reflection and wants to override the default behavior.
+  virtual const Reflection* GetReflection() const {
+    return GetMetadata().reflection;
+  }
+
+ protected:
+  // Get a struct containing the metadata for the Message. Most subclasses only
+  // need to implement this method, rather than the GetDescriptor() and
+  // GetReflection() wrappers.
+  virtual Metadata GetMetadata() const  = 0;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
@@ -758,12 +666,13 @@
   // For internal use only:  Registers a .proto file at static initialization
   // time, to be placed in generated_factory.  The first time GetPrototype()
   // is called with a descriptor from this file, |register_messages| will be
-  // called.  It must call InternalRegisterGeneratedMessage() (below) to
-  // register each message type in the file.  This strange mechanism is
-  // necessary because descriptors are built lazily, so we can't register
-  // types by their descriptor until we know that the descriptor exists.
-  static void InternalRegisterGeneratedFile(const char* filename,
-                                            void (*register_messages)());
+  // called, with the file name as the parameter.  It must call
+  // InternalRegisterGeneratedMessage() (below) to register each message type
+  // in the file.  This strange mechanism is necessary because descriptors are
+  // built lazily, so we can't register types by their descriptor until we
+  // know that the descriptor exists.  |filename| must be a permanent string.
+  static void InternalRegisterGeneratedFile(
+      const char* filename, void (*register_messages)(const string&));
 
   // For internal use only:  Registers a message type.  Called only by the
   // functions which are registered with InternalRegisterGeneratedFile(),
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
new file mode 100644
index 0000000..5e156f2
--- /dev/null
+++ b/src/google/protobuf/message_lite.cc
@@ -0,0 +1,282 @@
+// 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.
+
+// Authors: wink@google.com (Wink Saville),
+//          kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+
+#include <google/protobuf/message_lite.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+
+MessageLite::~MessageLite() {}
+
+string MessageLite::InitializationErrorString() const {
+  return "(cannot determine missing fields for lite message)";
+}
+
+namespace {
+
+string InitializationErrorMessage(const char* action,
+                                  const MessageLite& message) {
+  return strings::Substitute(
+    "Can't $0 message of type \"$1\" because it is missing required "
+    "fields: $2",
+    action, message.GetTypeName(),
+    message.InitializationErrorString());
+}
+
+// Several of the Parse methods below just do one thing and then call another
+// method.  In a naive implementation, we might have ParseFromString() call
+// ParseFromArray() which would call ParseFromZeroCopyStream() which would call
+// ParseFromCodedStream() which would call MergeFromCodedStream() which would
+// call MergePartialFromCodedStream().  However, when parsing very small
+// messages, every function call introduces significant overhead.  To avoid
+// this without reproducing code, we use these forced-inline helpers.
+//
+// Note:  GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not
+//   definitions.
+inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
+                                       MessageLite* message)
+                                       GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
+                                       MessageLite* message)
+                                       GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
+                                              MessageLite* message)
+                                              GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline bool InlineParseFromArray(const void* data, int size,
+                                 MessageLite* message)
+                                 GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline bool InlineParsePartialFromArray(const void* data, int size,
+                                        MessageLite* message)
+                                        GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
+bool InlineMergeFromCodedStream(io::CodedInputStream* input,
+                                MessageLite* message) {
+  if (!message->MergePartialFromCodedStream(input)) return false;
+  if (!message->IsInitialized()) {
+    GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
+    return false;
+  }
+  return true;
+}
+
+bool InlineParseFromCodedStream(io::CodedInputStream* input,
+                                MessageLite* message) {
+  message->Clear();
+  return InlineMergeFromCodedStream(input, message);
+}
+
+bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
+                                       MessageLite* message) {
+  message->Clear();
+  return message->MergePartialFromCodedStream(input);
+}
+
+bool InlineParseFromArray(const void* data, int size, MessageLite* message) {
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
+  return InlineParseFromCodedStream(&input, message) &&
+         input.ConsumedEntireMessage();
+}
+
+bool InlineParsePartialFromArray(const void* data, int size,
+                                 MessageLite* message) {
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
+  return InlineParsePartialFromCodedStream(&input, message) &&
+         input.ConsumedEntireMessage();
+}
+
+}  // namespace
+
+bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
+  return InlineMergeFromCodedStream(input, this);
+}
+
+bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
+  return InlineParseFromCodedStream(input, this);
+}
+
+bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
+  return InlineParsePartialFromCodedStream(input, this);
+}
+
+bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
+  io::CodedInputStream decoder(input);
+  return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
+}
+
+bool MessageLite::ParsePartialFromZeroCopyStream(
+    io::ZeroCopyInputStream* input) {
+  io::CodedInputStream decoder(input);
+  return ParsePartialFromCodedStream(&decoder) &&
+         decoder.ConsumedEntireMessage();
+}
+
+bool MessageLite::ParseFromBoundedZeroCopyStream(
+    io::ZeroCopyInputStream* input, int size) {
+  io::CodedInputStream decoder(input);
+  decoder.PushLimit(size);
+  return ParseFromCodedStream(&decoder) &&
+         decoder.ConsumedEntireMessage() &&
+         decoder.BytesUntilLimit() == 0;
+}
+
+bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
+    io::ZeroCopyInputStream* input, int size) {
+  io::CodedInputStream decoder(input);
+  decoder.PushLimit(size);
+  return ParsePartialFromCodedStream(&decoder) &&
+         decoder.ConsumedEntireMessage() &&
+         decoder.BytesUntilLimit() == 0;
+}
+
+bool MessageLite::ParseFromString(const string& data) {
+  return InlineParseFromArray(data.data(), data.size(), this);
+}
+
+bool MessageLite::ParsePartialFromString(const string& data) {
+  return InlineParsePartialFromArray(data.data(), data.size(), this);
+}
+
+bool MessageLite::ParseFromArray(const void* data, int size) {
+  return InlineParseFromArray(data, size, this);
+}
+
+bool MessageLite::ParsePartialFromArray(const void* data, int size) {
+  return InlineParsePartialFromArray(data, size, this);
+}
+
+
+// ===================================================================
+
+uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
+  // We only optimize this when using optimize_for = SPEED.  In other cases
+  // we just use the CodedOutputStream path.
+  int size = GetCachedSize();
+  io::ArrayOutputStream out(target, size);
+  io::CodedOutputStream coded_out(&out);
+  SerializeWithCachedSizes(&coded_out);
+  GOOGLE_CHECK(!coded_out.HadError());
+  return target + size;
+}
+
+bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
+  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+  return SerializePartialToCodedStream(output);
+}
+
+bool MessageLite::SerializePartialToCodedStream(
+    io::CodedOutputStream* output) const {
+  ByteSize();  // Force size to be cached.
+  SerializeWithCachedSizes(output);
+  return !output->HadError();
+}
+
+bool MessageLite::SerializeToZeroCopyStream(
+    io::ZeroCopyOutputStream* output) const {
+  io::CodedOutputStream encoder(output);
+  return SerializeToCodedStream(&encoder);
+}
+
+bool MessageLite::SerializePartialToZeroCopyStream(
+    io::ZeroCopyOutputStream* output) const {
+  io::CodedOutputStream encoder(output);
+  return SerializePartialToCodedStream(&encoder);
+}
+
+bool MessageLite::AppendToString(string* output) const {
+  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+  return AppendPartialToString(output);
+}
+
+bool MessageLite::AppendPartialToString(string* output) const {
+  int old_size = output->size();
+  int byte_size = ByteSize();
+  STLStringResizeUninitialized(output, old_size + byte_size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size);
+  uint8* end = SerializeWithCachedSizesToArray(start);
+  GOOGLE_CHECK_EQ(end - start, byte_size);
+  return true;
+}
+
+bool MessageLite::SerializeToString(string* output) const {
+  output->clear();
+  return AppendToString(output);
+}
+
+bool MessageLite::SerializePartialToString(string* output) const {
+  output->clear();
+  return AppendPartialToString(output);
+}
+
+bool MessageLite::SerializeToArray(void* data, int size) const {
+  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+  return SerializePartialToArray(data, size);
+}
+
+bool MessageLite::SerializePartialToArray(void* data, int size) const {
+  int byte_size = ByteSize();
+  if (size < byte_size) return false;
+  uint8* end =
+    SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(data));
+  GOOGLE_CHECK_EQ(end, reinterpret_cast<uint8*>(data) + byte_size);
+  return true;
+}
+
+string MessageLite::SerializeAsString() const {
+  // If the compiler implements the (Named) Return Value Optimization,
+  // the local variable 'result' will not actually reside on the stack
+  // of this function, but will be overlaid with the object that the
+  // caller supplied for the return value to be constructed in.
+  string output;
+  if (!AppendToString(&output))
+    output.clear();
+  return output;
+}
+
+string MessageLite::SerializePartialAsString() const {
+  string output;
+  if (!AppendPartialToString(&output))
+    output.clear();
+  return output;
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
new file mode 100644
index 0000000..d289d8c
--- /dev/null
+++ b/src/google/protobuf/message_lite.h
@@ -0,0 +1,237 @@
+// 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.
+
+// Authors: wink@google.com (Wink Saville),
+//          kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+
+#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__
+#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+
+namespace google {
+namespace protobuf {
+
+// Interface to light weight protocol messages.
+//
+// This interface is implemented by all protocol message objects.  Most
+// users will be more interested in the Message interface, which is a
+// subclass of MessageLite. Use MessageLite instead when you only need
+// the subset of features which it supports -- namely, nothing that uses
+// descriptors or reflection.  You can instruct the protocol compiler
+// to generate classes which implement only MessageLite, not the full
+// Message interface, by adding the following line to the .proto file:
+//
+//  option optimize_for = LITE_RUNTIME;
+//
+// This is particularly useful on resource-constrained systems where
+// the full protocol buffers runtime library is too big.
+//
+// Note that on non-constrained systems (e.g. servers) when you need
+// to link in lots of protocol definitions, a better way to reduce
+// total code footprint is to use optimize_for = CODE_SIZE.  This
+// will make the generated code smaller while still supporting all the
+// same features (at the expense of speed).  optimize_for = LITE_RUNTIME
+// is best when you only have a small number of message types linked
+// into your binary, in which case the size of the protocol buffers
+// runtime itself is the biggest problem.
+class LIBPROTOBUF_EXPORT MessageLite {
+ public:
+  inline MessageLite() {}
+  virtual ~MessageLite();
+
+  // Basic Operations ------------------------------------------------
+
+  // Get the name of this message type, e.g. "foo.bar.BazProto".
+  virtual string GetTypeName() const = 0;
+
+  // Construct a new instance of the same type.  Ownership is passed to the
+  // caller.
+  virtual MessageLite* New() const = 0;
+
+  // Clear all fields of the message and set them to their default values.
+  // Clear() avoids freeing memory, assuming that any memory allocated
+  // to hold parts of the message will be needed again to hold the next
+  // message.  If you actually want to free the memory used by a Message,
+  // you must delete it.
+  virtual void Clear() = 0;
+
+  // Quickly check if all required fields have values set.
+  virtual bool IsInitialized() const = 0;
+
+  // This is not implemented for Lite messages -- it just returns "(cannot
+  // determine missing fields for lite message)".  However, it is implemented
+  // for full messages.  See message.h.
+  virtual string InitializationErrorString() const;
+
+  // If |other| is the exact same class as this, calls MergeFrom().  Otherwise,
+  // results are undefined (probably crash).
+  virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
+
+  // Parsing ---------------------------------------------------------
+  // Methods for parsing in protocol buffer format.  Most of these are
+  // just simple wrappers around MergeFromCodedStream().
+
+  // 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.
+  bool ParseFromCodedStream(io::CodedInputStream* input);
+  // Like ParseFromCodedStream(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromCodedStream(io::CodedInputStream* input);
+  // Read a protocol buffer from the given zero-copy input stream.  If
+  // successful, the entire input will be consumed.
+  bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  // Like ParseFromZeroCopyStream(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  // Read a protocol buffer from the given zero-copy input stream, expecting
+  // the message to be exactly "size" bytes long.  If successful, exactly
+  // this many bytes will have been consumed from the input.
+  bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
+  // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
+  // missing required fields.
+  bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
+                                             int size);
+  // Parse a protocol buffer contained in a string.
+  bool ParseFromString(const string& data);
+  // Like ParseFromString(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromString(const string& data);
+  // Parse a protocol buffer contained in an array of bytes.
+  bool ParseFromArray(const void* data, int size);
+  // Like ParseFromArray(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromArray(const void* data, int size);
+
+
+  // Reads a protocol buffer from the stream and merges it into this
+  // Message.  Singular fields read from the input overwrite what is
+  // already in the Message and repeated fields are appended to those
+  // already present.
+  //
+  // It is the responsibility of the caller to call input->LastTagWas()
+  // (for groups) or input->ConsumedEntireMessage() (for non-groups) after
+  // this returns to verify that the message's end was delimited correctly.
+  //
+  // ParsefromCodedStream() is implemented as Clear() followed by
+  // MergeFromCodedStream().
+  bool MergeFromCodedStream(io::CodedInputStream* input);
+
+  // Like MergeFromCodedStream(), but succeeds even if required fields are
+  // missing in the input.
+  //
+  // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
+  // followed by IsInitialized().
+  virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
+
+  // Serialization ---------------------------------------------------
+  // Methods for serializing in protocol buffer format.  Most of these
+  // are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
+
+  // Write a protocol buffer of this message to the given output.  Returns
+  // false on a write error.  If the message is missing required fields,
+  // this may GOOGLE_CHECK-fail.
+  bool SerializeToCodedStream(io::CodedOutputStream* output) const;
+  // Like SerializeToCodedStream(), but allows missing required fields.
+  bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
+  // Write the message to the given zero-copy output stream.  All required
+  // fields must be set.
+  bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
+  // Like SerializeToZeroCopyStream(), but allows missing required fields.
+  bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
+  // Serialize the message and store it in the given string.  All required
+  // fields must be set.
+  bool SerializeToString(string* output) const;
+  // Like SerializeToString(), but allows missing required fields.
+  bool SerializePartialToString(string* output) const;
+  // Serialize the message and store it in the given byte array.  All required
+  // fields must be set.
+  bool SerializeToArray(void* data, int size) const;
+  // Like SerializeToArray(), but allows missing required fields.
+  bool SerializePartialToArray(void* data, int size) const;
+
+  // Make a string encoding the message. Is equivalent to calling
+  // SerializeToString() on a string and using that.  Returns the empty
+  // string if SerializeToString() would have returned an error.
+  // Note: If you intend to generate many such strings, you may
+  // reduce heap fragmentation by instead re-using the same string
+  // object with calls to SerializeToString().
+  string SerializeAsString() const;
+  // Like SerializeAsString(), but allows missing required fields.
+  string SerializePartialAsString() const;
+
+  // Like SerializeToString(), but appends to the data to the string's existing
+  // contents.  All required fields must be set.
+  bool AppendToString(string* output) const;
+  // Like AppendToString(), but allows missing required fields.
+  bool AppendPartialToString(string* output) const;
+
+  // Computes the serialized size of the message.  This recursively calls
+  // ByteSize() on all embedded messages.  If a subclass does not override
+  // this, it MUST override SetCachedSize().
+  virtual int ByteSize() const = 0;
+
+  // Serializes the message without recomputing the size.  The message must
+  // not have changed since the last call to ByteSize(); if it has, the results
+  // are undefined.
+  virtual void SerializeWithCachedSizes(
+      io::CodedOutputStream* output) const = 0;
+
+  // Like SerializeWithCachedSizes, but writes directly to *target, returning
+  // a pointer to the byte immediately after the last byte written.  "target"
+  // must point at a byte array of at least ByteSize() bytes.
+  virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const;
+
+  // Returns the result of the last call to ByteSize().  An embedded message's
+  // size is needed both to serialize it (because embedded messages are
+  // length-delimited) and to compute the outer message's size.  Caching
+  // the size avoids computing it multiple times.
+  //
+  // ByteSize() does not automatically use the cached size when available
+  // because this would require invalidating it every time the message was
+  // modified, which would be too hard and expensive.  (E.g. if a deeply-nested
+  // sub-message is changed, all of its parents' cached sizes would need to be
+  // invalidated, which is too much work for an otherwise inlined setter
+  // method.)
+  virtual int GetCachedSize() const = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index d0592de..46e6844 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -248,36 +248,6 @@
   EXPECT_FALSE(message.ParseFromArray("\014", 1));
 }
 
-TEST(MessageTest, FieldConstantValues) {
-  unittest::TestRequired message;
-  EXPECT_EQ(protobuf_unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalInt32FieldNumber, 1);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalgroupFieldNumber, 16);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalNestedMessageFieldNumber,
-    18);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalNestedEnumFieldNumber,
-    21);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber,
-    48);
-  EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber,
-    51);
-}
-
-TEST(MessageTest, ExtensionConstantValues) {
-  EXPECT_EQ(protobuf_unittest::TestRequired::kSingleFieldNumber, 1000);
-  EXPECT_EQ(protobuf_unittest::TestRequired::kMultiFieldNumber, 1001);
-  EXPECT_EQ(protobuf_unittest::kOptionalInt32ExtensionFieldNumber, 1);
-  EXPECT_EQ(protobuf_unittest::kOptionalgroupExtensionFieldNumber, 16);
-  EXPECT_EQ(protobuf_unittest::kOptionalNestedMessageExtensionFieldNumber, 18);
-  EXPECT_EQ(protobuf_unittest::kOptionalNestedEnumExtensionFieldNumber, 21);
-  EXPECT_EQ(protobuf_unittest::kRepeatedInt32ExtensionFieldNumber, 31);
-  EXPECT_EQ(protobuf_unittest::kRepeatedgroupExtensionFieldNumber, 46);
-  EXPECT_EQ(protobuf_unittest::kRepeatedNestedMessageExtensionFieldNumber, 48);
-  EXPECT_EQ(protobuf_unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
-}
-
 TEST(MessageFactoryTest, GeneratedFactoryLookup) {
   EXPECT_EQ(
     MessageFactory::generated_factory()->GetPrototype(
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index 2d5cb0a..270ef06 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -33,30 +33,51 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/common.h>
 
 namespace google {
 namespace protobuf {
-
-// HP C++ on Tru64 can't handle the stuff below being defined out-of-line, so
-// on that platform everything is defined in repeated_field.h.  On other
-// platforms, we want these to be out-of-line to avoid code bloat.
-#if !defined(__DECCXX) || !defined(__osf__)
-
 namespace internal {
 
-GenericRepeatedField::~GenericRepeatedField() {}
+void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
+  void** swap_elements       = elements_;
+  int    swap_current_size   = current_size_;
+  int    swap_allocated_size = allocated_size_;
+  int    swap_total_size     = total_size_;
+  // We may not be using initial_space_ but it's not worth checking.  Just
+  // copy it anyway.
+  void* swap_initial_space[kInitialSize];
+  memcpy(swap_initial_space, initial_space_, sizeof(initial_space_));
 
-} // namespace internal
+  elements_       = other->elements_;
+  current_size_   = other->current_size_;
+  allocated_size_ = other->allocated_size_;
+  total_size_     = other->total_size_;
+  memcpy(initial_space_, other->initial_space_, sizeof(initial_space_));
 
-template <>
-void RepeatedPtrField<string>::Clear() {
-  for (int i = 0; i < current_size_; i++) {
-    elements_[i]->clear();
+  other->elements_       = swap_elements;
+  other->current_size_   = swap_current_size;
+  other->allocated_size_ = swap_allocated_size;
+  other->total_size_     = swap_total_size;
+  memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space));
+
+  if (elements_ == other->initial_space_) {
+    elements_ = initial_space_;
   }
-  current_size_ = 0;
+  if (other->elements_ == initial_space_) {
+    other->elements_ = other->initial_space_;
+  }
 }
 
-#endif  // !defined(__DECCXX) || !defined(__osf__)
+string* StringTypeHandler::New() {
+  return new string;
+}
+void StringTypeHandler::Delete(string* value) {
+  delete value;
+}
+
+
+} // namespace internal
 
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 4446eaf..cbe2652 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -49,52 +49,16 @@
 #include <string>
 #include <iterator>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/message.h>
+#include <google/protobuf/message_lite.h>
 
 
 namespace google {
 namespace protobuf {
 
+class Message;
+
 namespace internal {
 
-// DO NOT USE GenericRepeatedField; it should be considered a private detail
-// of RepeatedField/RepeatedPtrField that may be removed in the future.
-// GeneratedMessageReflection needs to manipulate repeated fields in a
-// generic way, so we have them implement this interface.  This should ONLY
-// be used by GeneratedMessageReflection.  This would normally be very bad
-// design but GeneratedMessageReflection is a big efficiency hack anyway.
-//
-// TODO(kenton):  Implement something like Jeff's ProtoVoidPtrArray change.
-//   Then, get rid of GenericRepeatedField.
-class LIBPROTOBUF_EXPORT GenericRepeatedField {
- public:
-  inline GenericRepeatedField() {}
-#if defined(__DECCXX) && defined(__osf__)
-  // HP C++ on Tru64 has trouble when this is not defined inline.
-  virtual ~GenericRepeatedField() {}
-#else
-  virtual ~GenericRepeatedField();
-#endif
-
- private:
-  // We only want GeneratedMessageReflection to see and use these, so we
-  // make them private.  Yes, it is valid C++ for a subclass to implement
-  // a virtual method which is private in the superclass.  Crazy, huh?
-  friend class GeneratedMessageReflection;
-
-  virtual const void* GenericGet(int index) const = 0;
-  virtual void* GenericMutable(int index) = 0;
-  virtual void* GenericAdd() = 0;
-  virtual void GenericClear() = 0;
-  virtual void GenericRemoveLast() = 0;
-  virtual void GenericSwap(GenericRepeatedField *other) = 0;
-  virtual void GenericSwapElements(int index1, int index2) = 0;
-  virtual int GenericSize() const = 0;
-  virtual int GenericSpaceUsedExcludingSelf() const = 0;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GenericRepeatedField);
-};
-
 // We need this (from generated_message_reflection.cc).
 LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
 
@@ -105,7 +69,7 @@
 // not ever use a RepeatedField directly; they will use the get-by-index,
 // set-by-index, and add accessors that are generated for all repeated fields.
 template <typename Element>
-class RepeatedField : public internal::GenericRepeatedField {
+class RepeatedField {
  public:
   RepeatedField();
   ~RepeatedField();
@@ -138,7 +102,7 @@
   // Swap entire contents with "other".
   void Swap(RepeatedField* other);
 
-  // Swap two elements of a repeated field.
+  // Swap two elements.
   void SwapElements(int index1, int index2);
 
   // STL-like iterator support
@@ -154,18 +118,6 @@
   // sizeof(*this)
   int SpaceUsedExcludingSelf() const;
 
- private:  // See GenericRepeatedField for why this is private.
-  // implements GenericRepeatedField ---------------------------------
-  const void* GenericGet(int index) const;
-  void* GenericMutable(int index);
-  void* GenericAdd();
-  void GenericClear();
-  void GenericRemoveLast();
-  void GenericSwap(GenericRepeatedField *other);
-  void GenericSwapElements(int index1, int index2);
-  int GenericSize() const;
-  int GenericSpaceUsedExcludingSelf() const;
-
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField);
 
@@ -182,25 +134,158 @@
 template <typename It> class RepeatedPtrIterator;
 }  // namespace internal
 
+namespace internal {
+
+// This is the common base class for RepeatedPtrFields.  It deals only in void*
+// pointers.  Users should not use this interface directly.
+//
+// The methods of this interface correspond to the methods of RepeatedPtrField,
+// but may have a template argument called TypeHandler.  Its signature is:
+//   class TypeHandler {
+//    public:
+//     typedef MyType Type;
+//     static Type* New();
+//     static void Delete(Type*);
+//     static void Clear(Type*);
+//     static void Merge(const Type& from, Type* to);
+//
+//     // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
+//     static int SpaceUsed(const Type&);
+//   };
+class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
+ protected:
+  // The reflection implementation needs to call protected methods directly,
+  // reinterpreting pointers as being to Message instead of a specific Message
+  // subclass.
+  friend class GeneratedMessageReflection;
+
+  // ExtensionSet stores repeated message extensions as
+  // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to
+  // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf()
+  // reinterpreting MessageLite as Message.  ExtensionSet also needs to make
+  // use of AddFromCleared(), which is not part of the public interface.
+  friend class ExtensionSet;
+
+  RepeatedPtrFieldBase();
+
+  // Must be called from destructor.
+  template <typename TypeHandler>
+  void Destroy();
+
+  int size() const;
+
+  template <typename TypeHandler>
+  const typename TypeHandler::Type& Get(int index) const;
+  template <typename TypeHandler>
+  typename TypeHandler::Type* Mutable(int index);
+  template <typename TypeHandler>
+  typename TypeHandler::Type* Add();
+  template <typename TypeHandler>
+  void RemoveLast();
+  template <typename TypeHandler>
+  void Clear();
+  template <typename TypeHandler>
+  void MergeFrom(const RepeatedPtrFieldBase& other);
+
+  void Reserve(int new_size);
+
+  // Used for constructing iterators.
+  void* const* raw_data() const;
+
+  template <typename TypeHandler>
+  typename TypeHandler::Type** mutable_data();
+  template <typename TypeHandler>
+  const typename TypeHandler::Type* const* data() const;
+
+  void Swap(RepeatedPtrFieldBase* other);
+
+  void SwapElements(int index1, int index2);
+
+  template <typename TypeHandler>
+  int SpaceUsedExcludingSelf() const;
+
+  // Advanced memory management --------------------------------------
+
+  // Like Add(), but if there are no cleared objects to use, returns NULL.
+  template <typename TypeHandler>
+  typename TypeHandler::Type* AddFromCleared();
+
+  template <typename TypeHandler>
+  void AddAllocated(typename TypeHandler::Type* value);
+  template <typename TypeHandler>
+  typename TypeHandler::Type* ReleaseLast();
+
+  int ClearedCount();
+  template <typename TypeHandler>
+  void AddCleared(typename TypeHandler::Type* value);
+  template <typename TypeHandler>
+  typename TypeHandler::Type* ReleaseCleared();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
+
+  static const int kInitialSize = 4;
+
+  void** elements_;
+  int    current_size_;
+  int    allocated_size_;
+  int    total_size_;
+
+  void*  initial_space_[kInitialSize];
+
+  template <typename TypeHandler>
+  static inline typename TypeHandler::Type* cast(void* element) {
+    return reinterpret_cast<typename TypeHandler::Type*>(element);
+  }
+  template <typename TypeHandler>
+  static inline const typename TypeHandler::Type* cast(const void* element) {
+    return reinterpret_cast<const typename TypeHandler::Type*>(element);
+  }
+};
+
+template <typename GenericType>
+class GenericTypeHandler {
+ public:
+  typedef GenericType Type;
+  static GenericType* New() { return new GenericType; }
+  static void Delete(GenericType* value) { delete value; }
+  static void Clear(GenericType* value) { value->Clear(); }
+  static void Merge(const GenericType& from, GenericType* to) {
+    to->MergeFrom(from);
+  }
+  static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); }
+};
+
+template <>
+inline void GenericTypeHandler<MessageLite>::Merge(
+    const MessageLite& from, MessageLite* to) {
+  to->CheckTypeAndMergeFrom(from);
+}
+
+class LIBPROTOBUF_EXPORT StringTypeHandler {
+ public:
+  typedef string Type;
+  static string* New();
+  static void Delete(string* value);
+  static void Clear(string* value) { value->clear(); }
+  static void Merge(const string& from, string* to) { *to = from; }
+  static int SpaceUsed(const string& value)  {
+    return sizeof(value) + StringSpaceUsedExcludingSelf(value);
+  }
+};
+
+
+}  // namespace internal
+
 // RepeatedPtrField is like RepeatedField, but used for repeated strings or
 // Messages.
 template <typename Element>
-class RepeatedPtrField : public internal::GenericRepeatedField {
+class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
  public:
   RepeatedPtrField();
 
-  // This constructor is only defined for RepeatedPtrField<Message>.
-  // When a RepeatedPtrField is created using this constructor,
-  // prototype->New() will be called to allocate new elements, rather than
-  // just using the "new" operator.  This is useful for the implementation
-  // of DynamicMessage, but is not used by normal generated messages.
-  explicit RepeatedPtrField(const Message* prototype);
-
   ~RepeatedPtrField();
 
-  // Returns the prototype if one was passed to the constructor.
-  const Message* prototype() const;
-
   int size() const;
 
   const Element& Get(int index) const;
@@ -223,12 +308,12 @@
   // Swap entire contents with "other".
   void Swap(RepeatedPtrField* other);
 
-  // Swap two elements of a repeated field.
+  // Swap two elements.
   void SwapElements(int index1, int index2);
 
   // STL-like iterator support
-  typedef internal::RepeatedPtrIterator<Element**> iterator;
-  typedef internal::RepeatedPtrIterator<const Element* const*> const_iterator;
+  typedef internal::RepeatedPtrIterator<Element> iterator;
+  typedef internal::RepeatedPtrIterator<const Element> const_iterator;
 
   iterator begin();
   const_iterator begin() const;
@@ -239,6 +324,11 @@
   // excluding sizeof(*this).
   int SpaceUsedExcludingSelf() const;
 
+  // The spaced used just by the pointer array, not counting the objects pointed
+  // at.  Returns zero if the array is inlined (i.e. initial_space_ is being
+  // used).
+  int SpaceUsedByArray() const;
+
   // Advanced memory management --------------------------------------
   // When hardcore memory management becomes necessary -- as it often
   // does here at Google -- the following methods may be useful.
@@ -272,38 +362,16 @@
   // Requires:  ClearedCount() > 0
   Element* ReleaseCleared();
 
- private:  // See GenericRepeatedField for why this is private.
-  // implements GenericRepeatedField ---------------------------------
-  const void* GenericGet(int index) const;
-  void* GenericMutable(int index);
-  void* GenericAdd();
-  void GenericClear();
-  void GenericRemoveLast();
-  void GenericSwap(GenericRepeatedField *other);
-  void GenericSwapElements(int index1, int index2);
-  int GenericSize() const;
-  int GenericSpaceUsedExcludingSelf() const;
-
  private:
-  // Returns (an estimate of) the number of bytes used by an individual
-  // element.
-  int ElementSpaceUsed(Element* element) const;
+  class TypeHandler;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
 
-  static const int kInitialSize = 4;
-
-  // prototype_ is used for RepeatedPtrField<Message> only (see constructor).
-  const Message* prototype_;
-
-  Element** elements_;
-  int       current_size_;
-  int       allocated_size_;
-  int       total_size_;
-
-  Element*  initial_space_[kInitialSize];
-
-  Element* NewElement();
+  // prototype_ is used for RepeatedPtrField<Message> and
+  // RepeatedPtrField<MessageLite> only (see constructor).
+  // TODO(kenton):  Can we use some template magic to avoid wasting space on
+  //   this field when it isn't used?
+  const Element* prototype_;
 };
 
 // implementation ====================================================
@@ -412,7 +480,7 @@
 
 template <typename Element>
 void RepeatedField<Element>::SwapElements(int index1, int index2) {
-  swap(*Mutable(index1), *Mutable(index2));
+  swap(elements_[index1], elements_[index2]);
 }
 
 template <typename Element>
@@ -442,53 +510,6 @@
 }
 
 template <typename Element>
-const void* RepeatedField<Element>::GenericGet(int index) const {
-  GOOGLE_DCHECK_LT(index, size());
-  return elements_ + index;
-}
-
-template <typename Element>
-void* RepeatedField<Element>::GenericMutable(int index) {
-  return Mutable(index);
-}
-
-template <typename Element>
-void* RepeatedField<Element>::GenericAdd() {
-  Add(Element());
-  return Mutable(current_size_ - 1);
-}
-
-template <typename Element>
-void RepeatedField<Element>::GenericClear() {
-  Clear();
-}
-
-template <typename Element>
-void RepeatedField<Element>::GenericRemoveLast() {
-  RemoveLast();
-}
-
-template <typename Element>
-void RepeatedField<Element>::GenericSwap(GenericRepeatedField *other) {
-  Swap(down_cast<RepeatedField<Element>*>(other));
-}
-
-template <typename Element>
-void RepeatedField<Element>::GenericSwapElements(int index1, int index2) {
-  SwapElements(index1, index2);
-}
-
-template <typename Element>
-int RepeatedField<Element>::GenericSize() const {
-  return size();
-}
-
-template <typename Element>
-int RepeatedField<Element>::GenericSpaceUsedExcludingSelf() const {
-  return SpaceUsedExcludingSelf();
-}
-
-template <typename Element>
 inline void RepeatedField<Element>::Reserve(int new_size) {
   if (total_size_ >= new_size) return;
 
@@ -503,188 +524,123 @@
 
 // -------------------------------------------------------------------
 
-template <typename Element>
-inline RepeatedPtrField<Element>::RepeatedPtrField()
-  : prototype_(NULL),
-    elements_(initial_space_),
+namespace internal {
+
+inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
+  : elements_(initial_space_),
     current_size_(0),
     allocated_size_(0),
     total_size_(kInitialSize) {
 }
 
-template <>
-inline RepeatedPtrField<Message>::RepeatedPtrField(const Message* prototype)
-  : prototype_(prototype),
-    elements_(initial_space_),
-    current_size_(0),
-    allocated_size_(0),
-    total_size_(kInitialSize) {
-}
-
-template <typename Element>
-RepeatedPtrField<Element>::~RepeatedPtrField() {
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::Destroy() {
   for (int i = 0; i < allocated_size_; i++) {
-    delete elements_[i];
+    TypeHandler::Delete(cast<TypeHandler>(elements_[i]));
   }
   if (elements_ != initial_space_) {
     delete [] elements_;
   }
 }
 
-template <>
-inline const Message* RepeatedPtrField<Message>::prototype() const {
-  return prototype_;
-}
-
-
-template <typename Element>
-inline int RepeatedPtrField<Element>::size() const {
+inline int RepeatedPtrFieldBase::size() const {
   return current_size_;
 }
 
 
-template <typename Element>
-inline const Element& RepeatedPtrField<Element>::Get(int index) const {
+template <typename TypeHandler>
+inline const typename TypeHandler::Type&
+RepeatedPtrFieldBase::Get(int index) const {
   GOOGLE_DCHECK_LT(index, size());
-  return *elements_[index];
+  return *cast<TypeHandler>(elements_[index]);
 }
 
-template <typename Element>
-inline Element* RepeatedPtrField<Element>::Mutable(int index) {
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+RepeatedPtrFieldBase::Mutable(int index) {
   GOOGLE_DCHECK_LT(index, size());
-  return elements_[index];
+  return cast<TypeHandler>(elements_[index]);
 }
 
-template <typename Element>
-inline Element* RepeatedPtrField<Element>::Add() {
-  if (current_size_ < allocated_size_) return elements_[current_size_++];
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() {
+  if (current_size_ < allocated_size_) {
+    return cast<TypeHandler>(elements_[current_size_++]);
+  }
   if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
   ++allocated_size_;
-  return elements_[current_size_++] = NewElement();
+  typename TypeHandler::Type* result = TypeHandler::New();
+  elements_[current_size_++] = result;
+  return result;
 }
 
-template <typename Element>
-inline void RepeatedPtrField<Element>::RemoveLast() {
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::RemoveLast() {
   GOOGLE_DCHECK_GT(current_size_, 0);
-  elements_[--current_size_]->Clear();
+  TypeHandler::Clear(cast<TypeHandler>(elements_[--current_size_]));
 }
 
-template <>
-inline void RepeatedPtrField<string>::RemoveLast() {
-  GOOGLE_DCHECK_GT(current_size_, 0);
-  elements_[--current_size_]->clear();
-}
-
-template <typename Element>
-void RepeatedPtrField<Element>::Clear() {
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::Clear() {
   for (int i = 0; i < current_size_; i++) {
-    elements_[i]->Clear();
+    TypeHandler::Clear(cast<TypeHandler>(elements_[i]));
   }
   current_size_ = 0;
 }
 
-#if defined(__DECCXX) && defined(__osf__)
-// HP C++ on Tru64 has trouble when this is not defined inline.
-template <>
-inline void RepeatedPtrField<string>::Clear() {
-  for (int i = 0; i < current_size_; i++) {
-    elements_[i]->clear();
-  }
-  current_size_ = 0;
-}
-#else
-// Specialization defined in repeated_field.cc.
-template <>
-void LIBPROTOBUF_EXPORT RepeatedPtrField<string>::Clear();
-#endif
-
-template <typename Element>
-void RepeatedPtrField<Element>::MergeFrom(const RepeatedPtrField& other) {
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
   Reserve(current_size_ + other.current_size_);
   for (int i = 0; i < other.current_size_; i++) {
-    Add()->MergeFrom(other.Get(i));
+    TypeHandler::Merge(other.Get<TypeHandler>(i), Add<TypeHandler>());
   }
 }
 
-template <>
-inline void RepeatedPtrField<string>::MergeFrom(const RepeatedPtrField& other) {
-  Reserve(current_size_ + other.current_size_);
-  for (int i = 0; i < other.current_size_; i++) {
-    Add()->assign(other.Get(i));
-  }
-}
-
-
-template <typename Element>
-inline Element** RepeatedPtrField<Element>::mutable_data() {
+inline void* const* RepeatedPtrFieldBase::raw_data() const {
   return elements_;
 }
 
-template <typename Element>
-inline const Element* const* RepeatedPtrField<Element>::data() const {
-  return elements_;
+template <typename TypeHandler>
+inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
+  // TODO(kenton):  Breaks C++ aliasing rules.  We should probably remove this
+  //   method entirely.
+  return reinterpret_cast<typename TypeHandler::Type**>(elements_);
 }
 
-
-template <typename Element>
-void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
-  Element** swap_elements       = elements_;
-  int       swap_current_size   = current_size_;
-  int       swap_allocated_size = allocated_size_;
-  int       swap_total_size     = total_size_;
-  // We may not be using initial_space_ but it's not worth checking.  Just
-  // copy it anyway.
-  Element* swap_initial_space[kInitialSize];
-  memcpy(swap_initial_space, initial_space_, sizeof(initial_space_));
-
-  elements_       = other->elements_;
-  current_size_   = other->current_size_;
-  allocated_size_ = other->allocated_size_;
-  total_size_     = other->total_size_;
-  memcpy(initial_space_, other->initial_space_, sizeof(initial_space_));
-
-  other->elements_       = swap_elements;
-  other->current_size_   = swap_current_size;
-  other->allocated_size_ = swap_allocated_size;
-  other->total_size_     = swap_total_size;
-  memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space));
-
-  if (elements_ == other->initial_space_) {
-    elements_ = initial_space_;
-  }
-  if (other->elements_ == initial_space_) {
-    other->elements_ = other->initial_space_;
-  }
+template <typename TypeHandler>
+inline const typename TypeHandler::Type* const*
+RepeatedPtrFieldBase::data() const {
+  // TODO(kenton):  Breaks C++ aliasing rules.  We should probably remove this
+  //   method entirely.
+  return reinterpret_cast<const typename TypeHandler::Type* const*>(elements_);
 }
 
-template <typename Element>
-void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
+inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) {
   swap(elements_[index1], elements_[index2]);
 }
 
-template <typename Element>
-inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
+template <typename TypeHandler>
+inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
   int allocated_bytes =
       (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
   for (int i = 0; i < allocated_size_; ++i) {
-    allocated_bytes += ElementSpaceUsed(elements_[i]);
+    allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i]));
   }
   return allocated_bytes;
 }
 
-template <typename Element>
-inline int RepeatedPtrField<Element>::ElementSpaceUsed(Element* e) const {
-  return e->SpaceUsed();
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
+  if (current_size_ < allocated_size_) {
+    return cast<TypeHandler>(elements_[current_size_++]);
+  } else {
+    return NULL;
+  }
 }
 
-template <>
-inline int RepeatedPtrField<string>::ElementSpaceUsed(string* s) const {
-  return sizeof(*s) + internal::StringSpaceUsedExcludingSelf(*s);
-}
-
-
-template <typename Element>
-inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::AddAllocated(
+    typename TypeHandler::Type* value) {
   if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
   // We don't care about the order of cleared elements, so if there's one
   // in the way, just move it to the back of the array.
@@ -695,10 +651,11 @@
   elements_[current_size_++] = value;
 }
 
-template <typename Element>
-inline Element* RepeatedPtrField<Element>::ReleaseLast() {
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() {
   GOOGLE_DCHECK_GT(current_size_, 0);
-  Element* result = elements_[--current_size_];
+  typename TypeHandler::Type* result =
+      cast<TypeHandler>(elements_[--current_size_]);
   --allocated_size_;
   if (current_size_ < allocated_size_) {
     // There are cleared elements on the end; replace the removed element
@@ -709,93 +666,148 @@
 }
 
 
-template <typename Element>
-inline int RepeatedPtrField<Element>::ClearedCount() {
+inline int RepeatedPtrFieldBase::ClearedCount() {
   return allocated_size_ - current_size_;
 }
 
-template <typename Element>
-inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::AddCleared(
+    typename TypeHandler::Type* value) {
   if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
   elements_[allocated_size_++] = value;
 }
 
-template <typename Element>
-inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
   GOOGLE_DCHECK_GT(allocated_size_, current_size_);
-  return elements_[--allocated_size_];
+  return cast<TypeHandler>(elements_[--allocated_size_]);
 }
 
-
-template <typename Element>
-const void* RepeatedPtrField<Element>::GenericGet(int index) const {
-  return &Get(index);
-}
-
-template <typename Element>
-void* RepeatedPtrField<Element>::GenericMutable(int index) {
-  return Mutable(index);
-}
-
-template <typename Element>
-void* RepeatedPtrField<Element>::GenericAdd() {
-  return Add();
-}
-
-template <typename Element>
-void RepeatedPtrField<Element>::GenericClear() {
-  Clear();
-}
-
-template <typename Element>
-void RepeatedPtrField<Element>::GenericRemoveLast() {
-  RemoveLast();
-}
-
-template <typename Element>
-void RepeatedPtrField<Element>::GenericSwap(GenericRepeatedField *other) {
-  Swap(down_cast<RepeatedPtrField<Element>*>(other));
-}
-
-template <typename Element>
-void RepeatedPtrField<Element>::GenericSwapElements(int index1, int index2) {
-  SwapElements(index1, index2);
-}
-
-template <typename Element>
-int RepeatedPtrField<Element>::GenericSize() const {
-  return size();
-}
-
-template <typename Element>
-int RepeatedPtrField<Element>::GenericSpaceUsedExcludingSelf() const {
-  return SpaceUsedExcludingSelf();
-}
-
-
-template <typename Element>
-inline void RepeatedPtrField<Element>::Reserve(int new_size) {
+inline void RepeatedPtrFieldBase::Reserve(int new_size) {
   if (total_size_ >= new_size) return;
 
-  Element** old_elements = elements_;
+  void** old_elements = elements_;
   total_size_ = max(total_size_ * 2, new_size);
-  elements_ = new Element*[total_size_];
+  elements_ = new void*[total_size_];
   memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
   if (old_elements != initial_space_) {
     delete [] old_elements;
   }
 }
 
+}  // namespace internal
+
+// -------------------------------------------------------------------
+
 template <typename Element>
-inline Element* RepeatedPtrField<Element>::NewElement() {
-  return new Element;
+class RepeatedPtrField<Element>::TypeHandler
+    : public internal::GenericTypeHandler<Element> {};
+
+template <>
+class RepeatedPtrField<string>::TypeHandler
+    : public internal::StringTypeHandler {};
+
+
+template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField()
+  : prototype_(NULL) {
 }
 
-// RepeatedPtrField<Message> is allowed but requires a prototype since Message
-// is abstract.
-template <>
-inline Message* RepeatedPtrField<Message>::NewElement() {
-  return prototype_->New();
+template <typename Element>
+RepeatedPtrField<Element>::~RepeatedPtrField() {
+  Destroy<TypeHandler>();
+}
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::size() const {
+  return RepeatedPtrFieldBase::size();
+}
+
+template <typename Element>
+inline const Element& RepeatedPtrField<Element>::Get(int index) const {
+  return RepeatedPtrFieldBase::Get<TypeHandler>(index);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::Mutable(int index) {
+  return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::Add() {
+  return RepeatedPtrFieldBase::Add<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::RemoveLast() {
+  RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::Clear() {
+  RepeatedPtrFieldBase::Clear<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::MergeFrom(
+    const RepeatedPtrField& other) {
+  RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
+}
+
+template <typename Element>
+inline Element** RepeatedPtrField<Element>::mutable_data() {
+  return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
+}
+
+template <typename Element>
+inline const Element* const* RepeatedPtrField<Element>::data() const {
+  return RepeatedPtrFieldBase::data<TypeHandler>();
+}
+
+template <typename Element>
+void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
+  RepeatedPtrFieldBase::Swap(other);
+}
+
+template <typename Element>
+void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
+  RepeatedPtrFieldBase::SwapElements(index1, index2);
+}
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
+  return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
+  RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::ReleaseLast() {
+  return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>();
+}
+
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::ClearedCount() {
+  return RepeatedPtrFieldBase::ClearedCount();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
+  return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
+  return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::Reserve(int new_size) {
+  return RepeatedPtrFieldBase::Reserve(new_size);
 }
 
 // -------------------------------------------------------------------
@@ -805,26 +817,22 @@
 // STL-like iterator implementation for RepeatedPtrField.  You should not
 // refer to this class directly; use RepeatedPtrField<T>::iterator instead.
 //
-// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T**>, is
-// very similar to iterator_ptr<> in util/gtl/iterator_adaptors-inl.h,
-// but adds random-access operators and is slightly more specialized
-// for using T** as its base type. I didn't re-use the other class to
-// avoid an extra dependency.
+// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
+// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors-inl.h,
+// but adds random-access operators and is modified to wrap a void** base
+// iterator (since RepeatedPtrField stores its array as a void* array and
+// casting void** to T** would violate C++ aliasing rules).
 //
-// This code stolen from net/proto/proto-array-internal.h by Jeffrey Yasskin
+// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin
 // (jyasskin@google.com).
-template<typename It>
+template<typename Element>
 class RepeatedPtrIterator
     : public std::iterator<
-          std::random_access_iterator_tag,
-          typename internal::remove_pointer<
-              typename internal::remove_pointer<It>::type>::type> {
+          std::random_access_iterator_tag, Element> {
  public:
-  typedef RepeatedPtrIterator<It> iterator;
+  typedef RepeatedPtrIterator<Element> iterator;
   typedef std::iterator<
-          std::random_access_iterator_tag,
-          typename internal::remove_pointer<
-              typename internal::remove_pointer<It>::type>::type> superclass;
+          std::random_access_iterator_tag, Element> superclass;
 
   // Let the compiler know that these are type names, so we don't have to
   // write "typename" in front of them everywhere.
@@ -833,19 +841,21 @@
   typedef typename superclass::difference_type difference_type;
 
   RepeatedPtrIterator() : it_(NULL) {}
-  explicit RepeatedPtrIterator(const It& it) : it_(it) {}
+  explicit RepeatedPtrIterator(void* const* it) : it_(it) {}
 
   // Allow "upcasting" from RepeatedPtrIterator<T**> to
   // RepeatedPtrIterator<const T*const*>.
-  template<typename OtherIt>
-  RepeatedPtrIterator(const RepeatedPtrIterator<OtherIt>& other)
-      : it_(other.base()) {}
-
-  // Provide access to the wrapped iterator.
-  const It& base() const { return it_; }
+  template<typename OtherElement>
+  RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
+      : it_(other.it_) {
+    // Force a compiler error if the other type is not convertable to ours.
+    if (false) {
+      implicit_cast<Element*, OtherElement*>(0);
+    }
+  }
 
   // dereferenceable
-  reference operator*() const { return **it_; }
+  reference operator*() const { return *reinterpret_cast<Element*>(*it_); }
   pointer   operator->() const { return &(operator*()); }
 
   // {inc,dec}rementable
@@ -893,8 +903,11 @@
   difference_type operator-(const iterator& x) const { return it_ - x.it_; }
 
  private:
+  template<typename OtherElement>
+  friend class RepeatedPtrIterator;
+
   // The internal iterator.
-  It it_;
+  void* const* it_;
 };
 
 }  // namespace internal
@@ -902,22 +915,22 @@
 template <typename Element>
 inline typename RepeatedPtrField<Element>::iterator
 RepeatedPtrField<Element>::begin() {
-  return iterator(elements_);
+  return iterator(raw_data());
 }
 template <typename Element>
 inline typename RepeatedPtrField<Element>::const_iterator
 RepeatedPtrField<Element>::begin() const {
-  return iterator(elements_);
+  return iterator(raw_data());
 }
 template <typename Element>
 inline typename RepeatedPtrField<Element>::iterator
 RepeatedPtrField<Element>::end() {
-  return iterator(elements_ + current_size_);
+  return iterator(raw_data() + size());
 }
 template <typename Element>
 inline typename RepeatedPtrField<Element>::const_iterator
 RepeatedPtrField<Element>::end() const {
-  return iterator(elements_ + current_size_);
+  return iterator(raw_data() + size());
 }
 
 // Iterators and helper functions that follow the spirit of the STL
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index ace1077..069f33e 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -181,6 +181,14 @@
 #define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
 #endif
 
+#undef GOOGLE_ATTRIBUTE_DEPRECATED
+#ifdef __GNUC__
+// If the method/variable/type is used anywhere, produce a warning.
+#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated))
+#else
+#define GOOGLE_ATTRIBUTE_DEPRECATED
+#endif
+
 // ===================================================================
 // from google3/base/basictypes.h
 
@@ -642,24 +650,24 @@
 
 #define GOOGLE_CHECK(EXPRESSION) \
   GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
-#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK(A == B)
-#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK(A != B)
-#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK(A <  B)
-#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK(A <= B)
-#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK(A >  B)
-#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK(A >= B)
+#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
+#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
+#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) <  (B))
+#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
+#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) >  (B))
+#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
 
 #ifdef NDEBUG
 
 #define GOOGLE_DLOG GOOGLE_LOG_IF(false, INFO)
 
 #define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
-#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK(A == B)
-#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK(A != B)
-#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK(A <  B)
-#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK(A <= B)
-#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK(A >  B)
-#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK(A >= B)
+#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
+#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
+#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) <  (B))
+#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
+#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) >  (B))
+#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
 
 #else  // NDEBUG
 
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index e3e67f6..0637c0a 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -33,7 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #ifdef _WIN32
-// Verify that #icnluding windows.h does not break anything (e.g. because
+// Verify that #including windows.h does not break anything (e.g. because
 // windows.h #defines GetMessage() as a macro).
 #include <windows.h>
 #endif
@@ -86,7 +86,7 @@
     message,
     message->GetDescriptor()->FindFieldByName("optional_cord"),
     "125");
-#endif
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
   // -----------------------------------------------------------------
 
@@ -124,7 +124,7 @@
     message,
     message->GetDescriptor()->FindFieldByName("repeated_cord"),
     "225");
-#endif
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
   // Add a second one of each field.
   message->add_repeated_int32   (301);
@@ -161,7 +161,7 @@
     message,
     message->GetDescriptor()->FindFieldByName("repeated_cord"),
     "325");
-#endif
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
   // -----------------------------------------------------------------
 
@@ -194,7 +194,7 @@
     message,
     message->GetDescriptor()->FindFieldByName("default_cord"),
     "425");
-#endif
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 }
 
 // -------------------------------------------------------------------
@@ -234,7 +234,7 @@
     message,
     message->GetDescriptor()->FindFieldByName("repeated_cord"),
     1, "425");
-#endif
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 }
 
 // -------------------------------------------------------------------
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index e581f41..5a6ec88 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -102,7 +102,8 @@
   static void ExpectLastRepeatedExtensionsRemoved(
       const unittest::TestAllExtensions& message);
 
-  // Check that all repeated fields have had their first and last elements swapped.
+  // Check that all repeated fields have had their first and last elements
+  // swapped.
   static void ExpectRepeatedsSwapped(const unittest::TestAllTypes& message);
   static void ExpectRepeatedExtensionsSwapped(
       const unittest::TestAllExtensions& message);
diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
new file mode 100644
index 0000000..d7140e0
--- /dev/null
+++ b/src/google/protobuf/test_util_lite.cc
@@ -0,0 +1,1502 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/test_util_lite.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 {
+
+void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) {
+  message->set_optional_int32   (101);
+  message->set_optional_int64   (102);
+  message->set_optional_uint32  (103);
+  message->set_optional_uint64  (104);
+  message->set_optional_sint32  (105);
+  message->set_optional_sint64  (106);
+  message->set_optional_fixed32 (107);
+  message->set_optional_fixed64 (108);
+  message->set_optional_sfixed32(109);
+  message->set_optional_sfixed64(110);
+  message->set_optional_float   (111);
+  message->set_optional_double  (112);
+  message->set_optional_bool    (true);
+  message->set_optional_string  ("115");
+  message->set_optional_bytes   ("116");
+
+  message->mutable_optionalgroup           ()->set_a(117);
+  message->mutable_optional_nested_message ()->set_bb(118);
+  message->mutable_optional_foreign_message()->set_c(119);
+  message->mutable_optional_import_message ()->set_d(120);
+
+  message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ );
+  message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ      );
+  message->set_optional_import_enum (unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->add_repeated_int32   (201);
+  message->add_repeated_int64   (202);
+  message->add_repeated_uint32  (203);
+  message->add_repeated_uint64  (204);
+  message->add_repeated_sint32  (205);
+  message->add_repeated_sint64  (206);
+  message->add_repeated_fixed32 (207);
+  message->add_repeated_fixed64 (208);
+  message->add_repeated_sfixed32(209);
+  message->add_repeated_sfixed64(210);
+  message->add_repeated_float   (211);
+  message->add_repeated_double  (212);
+  message->add_repeated_bool    (true);
+  message->add_repeated_string  ("215");
+  message->add_repeated_bytes   ("216");
+
+  message->add_repeatedgroup           ()->set_a(217);
+  message->add_repeated_nested_message ()->set_bb(218);
+  message->add_repeated_foreign_message()->set_c(219);
+  message->add_repeated_import_message ()->set_d(220);
+
+  message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR );
+  message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR      );
+  message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAR);
+
+
+  // Add a second one of each field.
+  message->add_repeated_int32   (301);
+  message->add_repeated_int64   (302);
+  message->add_repeated_uint32  (303);
+  message->add_repeated_uint64  (304);
+  message->add_repeated_sint32  (305);
+  message->add_repeated_sint64  (306);
+  message->add_repeated_fixed32 (307);
+  message->add_repeated_fixed64 (308);
+  message->add_repeated_sfixed32(309);
+  message->add_repeated_sfixed64(310);
+  message->add_repeated_float   (311);
+  message->add_repeated_double  (312);
+  message->add_repeated_bool    (false);
+  message->add_repeated_string  ("315");
+  message->add_repeated_bytes   ("316");
+
+  message->add_repeatedgroup           ()->set_a(317);
+  message->add_repeated_nested_message ()->set_bb(318);
+  message->add_repeated_foreign_message()->set_c(319);
+  message->add_repeated_import_message ()->set_d(320);
+
+  message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ );
+  message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ      );
+  message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->set_default_int32   (401);
+  message->set_default_int64   (402);
+  message->set_default_uint32  (403);
+  message->set_default_uint64  (404);
+  message->set_default_sint32  (405);
+  message->set_default_sint64  (406);
+  message->set_default_fixed32 (407);
+  message->set_default_fixed64 (408);
+  message->set_default_sfixed32(409);
+  message->set_default_sfixed64(410);
+  message->set_default_float   (411);
+  message->set_default_double  (412);
+  message->set_default_bool    (false);
+  message->set_default_string  ("415");
+  message->set_default_bytes   ("416");
+
+  message->set_default_nested_enum (unittest::TestAllTypesLite::FOO );
+  message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO      );
+  message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO);
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* message) {
+  message->set_repeated_int32   (1, 501);
+  message->set_repeated_int64   (1, 502);
+  message->set_repeated_uint32  (1, 503);
+  message->set_repeated_uint64  (1, 504);
+  message->set_repeated_sint32  (1, 505);
+  message->set_repeated_sint64  (1, 506);
+  message->set_repeated_fixed32 (1, 507);
+  message->set_repeated_fixed64 (1, 508);
+  message->set_repeated_sfixed32(1, 509);
+  message->set_repeated_sfixed64(1, 510);
+  message->set_repeated_float   (1, 511);
+  message->set_repeated_double  (1, 512);
+  message->set_repeated_bool    (1, true);
+  message->set_repeated_string  (1, "515");
+  message->set_repeated_bytes   (1, "516");
+
+  message->mutable_repeatedgroup           (1)->set_a(517);
+  message->mutable_repeated_nested_message (1)->set_bb(518);
+  message->mutable_repeated_foreign_message(1)->set_c(519);
+  message->mutable_repeated_import_message (1)->set_d(520);
+
+  message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO );
+  message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO      );
+  message->set_repeated_import_enum (1, unittest_import::IMPORT_LITE_FOO);
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectAllFieldsSet(
+    const unittest::TestAllTypesLite& message) {
+  EXPECT_TRUE(message.has_optional_int32   ());
+  EXPECT_TRUE(message.has_optional_int64   ());
+  EXPECT_TRUE(message.has_optional_uint32  ());
+  EXPECT_TRUE(message.has_optional_uint64  ());
+  EXPECT_TRUE(message.has_optional_sint32  ());
+  EXPECT_TRUE(message.has_optional_sint64  ());
+  EXPECT_TRUE(message.has_optional_fixed32 ());
+  EXPECT_TRUE(message.has_optional_fixed64 ());
+  EXPECT_TRUE(message.has_optional_sfixed32());
+  EXPECT_TRUE(message.has_optional_sfixed64());
+  EXPECT_TRUE(message.has_optional_float   ());
+  EXPECT_TRUE(message.has_optional_double  ());
+  EXPECT_TRUE(message.has_optional_bool    ());
+  EXPECT_TRUE(message.has_optional_string  ());
+  EXPECT_TRUE(message.has_optional_bytes   ());
+
+  EXPECT_TRUE(message.has_optionalgroup           ());
+  EXPECT_TRUE(message.has_optional_nested_message ());
+  EXPECT_TRUE(message.has_optional_foreign_message());
+  EXPECT_TRUE(message.has_optional_import_message ());
+
+  EXPECT_TRUE(message.optionalgroup           ().has_a());
+  EXPECT_TRUE(message.optional_nested_message ().has_bb());
+  EXPECT_TRUE(message.optional_foreign_message().has_c());
+  EXPECT_TRUE(message.optional_import_message ().has_d());
+
+  EXPECT_TRUE(message.has_optional_nested_enum ());
+  EXPECT_TRUE(message.has_optional_foreign_enum());
+  EXPECT_TRUE(message.has_optional_import_enum ());
+
+
+  EXPECT_EQ(101  , message.optional_int32   ());
+  EXPECT_EQ(102  , message.optional_int64   ());
+  EXPECT_EQ(103  , message.optional_uint32  ());
+  EXPECT_EQ(104  , message.optional_uint64  ());
+  EXPECT_EQ(105  , message.optional_sint32  ());
+  EXPECT_EQ(106  , message.optional_sint64  ());
+  EXPECT_EQ(107  , message.optional_fixed32 ());
+  EXPECT_EQ(108  , message.optional_fixed64 ());
+  EXPECT_EQ(109  , message.optional_sfixed32());
+  EXPECT_EQ(110  , message.optional_sfixed64());
+  EXPECT_EQ(111  , message.optional_float   ());
+  EXPECT_EQ(112  , message.optional_double  ());
+  EXPECT_EQ(true , message.optional_bool    ());
+  EXPECT_EQ("115", message.optional_string  ());
+  EXPECT_EQ("116", message.optional_bytes   ());
+
+  EXPECT_EQ(117, message.optionalgroup           ().a());
+  EXPECT_EQ(118, message.optional_nested_message ().bb());
+  EXPECT_EQ(119, message.optional_foreign_message().c());
+  EXPECT_EQ(120, message.optional_import_message ().d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.optional_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.optional_import_enum ());
+
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_EQ(true , message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0));
+
+  EXPECT_EQ(301  , message.repeated_int32   (1));
+  EXPECT_EQ(302  , message.repeated_int64   (1));
+  EXPECT_EQ(303  , message.repeated_uint32  (1));
+  EXPECT_EQ(304  , message.repeated_uint64  (1));
+  EXPECT_EQ(305  , message.repeated_sint32  (1));
+  EXPECT_EQ(306  , message.repeated_sint64  (1));
+  EXPECT_EQ(307  , message.repeated_fixed32 (1));
+  EXPECT_EQ(308  , message.repeated_fixed64 (1));
+  EXPECT_EQ(309  , message.repeated_sfixed32(1));
+  EXPECT_EQ(310  , message.repeated_sfixed64(1));
+  EXPECT_EQ(311  , message.repeated_float   (1));
+  EXPECT_EQ(312  , message.repeated_double  (1));
+  EXPECT_EQ(false, message.repeated_bool    (1));
+  EXPECT_EQ("315", message.repeated_string  (1));
+  EXPECT_EQ("316", message.repeated_bytes   (1));
+
+  EXPECT_EQ(317, message.repeatedgroup           (1).a());
+  EXPECT_EQ(318, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(319, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(320, message.repeated_import_message (1).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.repeated_import_enum (1));
+
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(message.has_default_int32   ());
+  EXPECT_TRUE(message.has_default_int64   ());
+  EXPECT_TRUE(message.has_default_uint32  ());
+  EXPECT_TRUE(message.has_default_uint64  ());
+  EXPECT_TRUE(message.has_default_sint32  ());
+  EXPECT_TRUE(message.has_default_sint64  ());
+  EXPECT_TRUE(message.has_default_fixed32 ());
+  EXPECT_TRUE(message.has_default_fixed64 ());
+  EXPECT_TRUE(message.has_default_sfixed32());
+  EXPECT_TRUE(message.has_default_sfixed64());
+  EXPECT_TRUE(message.has_default_float   ());
+  EXPECT_TRUE(message.has_default_double  ());
+  EXPECT_TRUE(message.has_default_bool    ());
+  EXPECT_TRUE(message.has_default_string  ());
+  EXPECT_TRUE(message.has_default_bytes   ());
+
+  EXPECT_TRUE(message.has_default_nested_enum ());
+  EXPECT_TRUE(message.has_default_foreign_enum());
+  EXPECT_TRUE(message.has_default_import_enum ());
+
+
+  EXPECT_EQ(401  , message.default_int32   ());
+  EXPECT_EQ(402  , message.default_int64   ());
+  EXPECT_EQ(403  , message.default_uint32  ());
+  EXPECT_EQ(404  , message.default_uint64  ());
+  EXPECT_EQ(405  , message.default_sint32  ());
+  EXPECT_EQ(406  , message.default_sint64  ());
+  EXPECT_EQ(407  , message.default_fixed32 ());
+  EXPECT_EQ(408  , message.default_fixed64 ());
+  EXPECT_EQ(409  , message.default_sfixed32());
+  EXPECT_EQ(410  , message.default_sfixed64());
+  EXPECT_EQ(411  , message.default_float   ());
+  EXPECT_EQ(412  , message.default_double  ());
+  EXPECT_EQ(false, message.default_bool    ());
+  EXPECT_EQ("415", message.default_string  ());
+  EXPECT_EQ("416", message.default_bytes   ());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.default_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.default_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ());
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) {
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(message.has_optional_int32   ());
+  EXPECT_FALSE(message.has_optional_int64   ());
+  EXPECT_FALSE(message.has_optional_uint32  ());
+  EXPECT_FALSE(message.has_optional_uint64  ());
+  EXPECT_FALSE(message.has_optional_sint32  ());
+  EXPECT_FALSE(message.has_optional_sint64  ());
+  EXPECT_FALSE(message.has_optional_fixed32 ());
+  EXPECT_FALSE(message.has_optional_fixed64 ());
+  EXPECT_FALSE(message.has_optional_sfixed32());
+  EXPECT_FALSE(message.has_optional_sfixed64());
+  EXPECT_FALSE(message.has_optional_float   ());
+  EXPECT_FALSE(message.has_optional_double  ());
+  EXPECT_FALSE(message.has_optional_bool    ());
+  EXPECT_FALSE(message.has_optional_string  ());
+  EXPECT_FALSE(message.has_optional_bytes   ());
+
+  EXPECT_FALSE(message.has_optionalgroup           ());
+  EXPECT_FALSE(message.has_optional_nested_message ());
+  EXPECT_FALSE(message.has_optional_foreign_message());
+  EXPECT_FALSE(message.has_optional_import_message ());
+
+  EXPECT_FALSE(message.has_optional_nested_enum ());
+  EXPECT_FALSE(message.has_optional_foreign_enum());
+  EXPECT_FALSE(message.has_optional_import_enum ());
+
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , message.optional_int32   ());
+  EXPECT_EQ(0    , message.optional_int64   ());
+  EXPECT_EQ(0    , message.optional_uint32  ());
+  EXPECT_EQ(0    , message.optional_uint64  ());
+  EXPECT_EQ(0    , message.optional_sint32  ());
+  EXPECT_EQ(0    , message.optional_sint64  ());
+  EXPECT_EQ(0    , message.optional_fixed32 ());
+  EXPECT_EQ(0    , message.optional_fixed64 ());
+  EXPECT_EQ(0    , message.optional_sfixed32());
+  EXPECT_EQ(0    , message.optional_sfixed64());
+  EXPECT_EQ(0    , message.optional_float   ());
+  EXPECT_EQ(0    , message.optional_double  ());
+  EXPECT_EQ(false, message.optional_bool    ());
+  EXPECT_EQ(""   , message.optional_string  ());
+  EXPECT_EQ(""   , message.optional_bytes   ());
+
+  // Embedded messages should also be clear.
+  EXPECT_FALSE(message.optionalgroup           ().has_a());
+  EXPECT_FALSE(message.optional_nested_message ().has_bb());
+  EXPECT_FALSE(message.optional_foreign_message().has_c());
+  EXPECT_FALSE(message.optional_import_message ().has_d());
+
+  EXPECT_EQ(0, message.optionalgroup           ().a());
+  EXPECT_EQ(0, message.optional_nested_message ().bb());
+  EXPECT_EQ(0, message.optional_foreign_message().c());
+  EXPECT_EQ(0, message.optional_import_message ().d());
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.optional_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.optional_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.optional_import_enum ());
+
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, message.repeated_int32_size   ());
+  EXPECT_EQ(0, message.repeated_int64_size   ());
+  EXPECT_EQ(0, message.repeated_uint32_size  ());
+  EXPECT_EQ(0, message.repeated_uint64_size  ());
+  EXPECT_EQ(0, message.repeated_sint32_size  ());
+  EXPECT_EQ(0, message.repeated_sint64_size  ());
+  EXPECT_EQ(0, message.repeated_fixed32_size ());
+  EXPECT_EQ(0, message.repeated_fixed64_size ());
+  EXPECT_EQ(0, message.repeated_sfixed32_size());
+  EXPECT_EQ(0, message.repeated_sfixed64_size());
+  EXPECT_EQ(0, message.repeated_float_size   ());
+  EXPECT_EQ(0, message.repeated_double_size  ());
+  EXPECT_EQ(0, message.repeated_bool_size    ());
+  EXPECT_EQ(0, message.repeated_string_size  ());
+  EXPECT_EQ(0, message.repeated_bytes_size   ());
+
+  EXPECT_EQ(0, message.repeatedgroup_size           ());
+  EXPECT_EQ(0, message.repeated_nested_message_size ());
+  EXPECT_EQ(0, message.repeated_foreign_message_size());
+  EXPECT_EQ(0, message.repeated_import_message_size ());
+  EXPECT_EQ(0, message.repeated_nested_enum_size    ());
+  EXPECT_EQ(0, message.repeated_foreign_enum_size   ());
+  EXPECT_EQ(0, message.repeated_import_enum_size    ());
+
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(message.has_default_int32   ());
+  EXPECT_FALSE(message.has_default_int64   ());
+  EXPECT_FALSE(message.has_default_uint32  ());
+  EXPECT_FALSE(message.has_default_uint64  ());
+  EXPECT_FALSE(message.has_default_sint32  ());
+  EXPECT_FALSE(message.has_default_sint64  ());
+  EXPECT_FALSE(message.has_default_fixed32 ());
+  EXPECT_FALSE(message.has_default_fixed64 ());
+  EXPECT_FALSE(message.has_default_sfixed32());
+  EXPECT_FALSE(message.has_default_sfixed64());
+  EXPECT_FALSE(message.has_default_float   ());
+  EXPECT_FALSE(message.has_default_double  ());
+  EXPECT_FALSE(message.has_default_bool    ());
+  EXPECT_FALSE(message.has_default_string  ());
+  EXPECT_FALSE(message.has_default_bytes   ());
+
+  EXPECT_FALSE(message.has_default_nested_enum ());
+  EXPECT_FALSE(message.has_default_foreign_enum());
+  EXPECT_FALSE(message.has_default_import_enum ());
+
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , message.default_int32   ());
+  EXPECT_EQ( 42    , message.default_int64   ());
+  EXPECT_EQ( 43    , message.default_uint32  ());
+  EXPECT_EQ( 44    , message.default_uint64  ());
+  EXPECT_EQ(-45    , message.default_sint32  ());
+  EXPECT_EQ( 46    , message.default_sint64  ());
+  EXPECT_EQ( 47    , message.default_fixed32 ());
+  EXPECT_EQ( 48    , message.default_fixed64 ());
+  EXPECT_EQ( 49    , message.default_sfixed32());
+  EXPECT_EQ(-50    , message.default_sfixed64());
+  EXPECT_EQ( 51.5  , message.default_float   ());
+  EXPECT_EQ( 52e3  , message.default_double  ());
+  EXPECT_EQ(true   , message.default_bool    ());
+  EXPECT_EQ("hello", message.default_string  ());
+  EXPECT_EQ("world", message.default_bytes   ());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.default_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.default_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ());
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectRepeatedFieldsModified(
+    const unittest::TestAllTypesLite& message) {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_EQ(true , message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0));
+
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(501  , message.repeated_int32   (1));
+  EXPECT_EQ(502  , message.repeated_int64   (1));
+  EXPECT_EQ(503  , message.repeated_uint32  (1));
+  EXPECT_EQ(504  , message.repeated_uint64  (1));
+  EXPECT_EQ(505  , message.repeated_sint32  (1));
+  EXPECT_EQ(506  , message.repeated_sint64  (1));
+  EXPECT_EQ(507  , message.repeated_fixed32 (1));
+  EXPECT_EQ(508  , message.repeated_fixed64 (1));
+  EXPECT_EQ(509  , message.repeated_sfixed32(1));
+  EXPECT_EQ(510  , message.repeated_sfixed64(1));
+  EXPECT_EQ(511  , message.repeated_float   (1));
+  EXPECT_EQ(512  , message.repeated_double  (1));
+  EXPECT_EQ(true , message.repeated_bool    (1));
+  EXPECT_EQ("515", message.repeated_string  (1));
+  EXPECT_EQ("516", message.repeated_bytes   (1));
+
+  EXPECT_EQ(517, message.repeatedgroup           (1).a());
+  EXPECT_EQ(518, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(519, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(520, message.repeated_import_message (1).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.repeated_import_enum (1));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::SetPackedFields(unittest::TestPackedTypesLite* message) {
+  message->add_packed_int32   (601);
+  message->add_packed_int64   (602);
+  message->add_packed_uint32  (603);
+  message->add_packed_uint64  (604);
+  message->add_packed_sint32  (605);
+  message->add_packed_sint64  (606);
+  message->add_packed_fixed32 (607);
+  message->add_packed_fixed64 (608);
+  message->add_packed_sfixed32(609);
+  message->add_packed_sfixed64(610);
+  message->add_packed_float   (611);
+  message->add_packed_double  (612);
+  message->add_packed_bool    (true);
+  message->add_packed_enum    (unittest::FOREIGN_LITE_BAR);
+  // add a second one of each field
+  message->add_packed_int32   (701);
+  message->add_packed_int64   (702);
+  message->add_packed_uint32  (703);
+  message->add_packed_uint64  (704);
+  message->add_packed_sint32  (705);
+  message->add_packed_sint64  (706);
+  message->add_packed_fixed32 (707);
+  message->add_packed_fixed64 (708);
+  message->add_packed_sfixed32(709);
+  message->add_packed_sfixed64(710);
+  message->add_packed_float   (711);
+  message->add_packed_double  (712);
+  message->add_packed_bool    (false);
+  message->add_packed_enum    (unittest::FOREIGN_LITE_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyPackedFields(unittest::TestPackedTypesLite* message) {
+  message->set_packed_int32   (1, 801);
+  message->set_packed_int64   (1, 802);
+  message->set_packed_uint32  (1, 803);
+  message->set_packed_uint64  (1, 804);
+  message->set_packed_sint32  (1, 805);
+  message->set_packed_sint64  (1, 806);
+  message->set_packed_fixed32 (1, 807);
+  message->set_packed_fixed64 (1, 808);
+  message->set_packed_sfixed32(1, 809);
+  message->set_packed_sfixed64(1, 810);
+  message->set_packed_float   (1, 811);
+  message->set_packed_double  (1, 812);
+  message->set_packed_bool    (1, true);
+  message->set_packed_enum    (1, unittest::FOREIGN_LITE_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedFieldsSet(
+    const unittest::TestPackedTypesLite& message) {
+  ASSERT_EQ(2, message.packed_int32_size   ());
+  ASSERT_EQ(2, message.packed_int64_size   ());
+  ASSERT_EQ(2, message.packed_uint32_size  ());
+  ASSERT_EQ(2, message.packed_uint64_size  ());
+  ASSERT_EQ(2, message.packed_sint32_size  ());
+  ASSERT_EQ(2, message.packed_sint64_size  ());
+  ASSERT_EQ(2, message.packed_fixed32_size ());
+  ASSERT_EQ(2, message.packed_fixed64_size ());
+  ASSERT_EQ(2, message.packed_sfixed32_size());
+  ASSERT_EQ(2, message.packed_sfixed64_size());
+  ASSERT_EQ(2, message.packed_float_size   ());
+  ASSERT_EQ(2, message.packed_double_size  ());
+  ASSERT_EQ(2, message.packed_bool_size    ());
+  ASSERT_EQ(2, message.packed_enum_size    ());
+
+  EXPECT_EQ(601  , message.packed_int32   (0));
+  EXPECT_EQ(602  , message.packed_int64   (0));
+  EXPECT_EQ(603  , message.packed_uint32  (0));
+  EXPECT_EQ(604  , message.packed_uint64  (0));
+  EXPECT_EQ(605  , message.packed_sint32  (0));
+  EXPECT_EQ(606  , message.packed_sint64  (0));
+  EXPECT_EQ(607  , message.packed_fixed32 (0));
+  EXPECT_EQ(608  , message.packed_fixed64 (0));
+  EXPECT_EQ(609  , message.packed_sfixed32(0));
+  EXPECT_EQ(610  , message.packed_sfixed64(0));
+  EXPECT_EQ(611  , message.packed_float   (0));
+  EXPECT_EQ(612  , message.packed_double  (0));
+  EXPECT_EQ(true , message.packed_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0));
+
+  EXPECT_EQ(701  , message.packed_int32   (1));
+  EXPECT_EQ(702  , message.packed_int64   (1));
+  EXPECT_EQ(703  , message.packed_uint32  (1));
+  EXPECT_EQ(704  , message.packed_uint64  (1));
+  EXPECT_EQ(705  , message.packed_sint32  (1));
+  EXPECT_EQ(706  , message.packed_sint64  (1));
+  EXPECT_EQ(707  , message.packed_fixed32 (1));
+  EXPECT_EQ(708  , message.packed_fixed64 (1));
+  EXPECT_EQ(709  , message.packed_sfixed32(1));
+  EXPECT_EQ(710  , message.packed_sfixed64(1));
+  EXPECT_EQ(711  , message.packed_float   (1));
+  EXPECT_EQ(712  , message.packed_double  (1));
+  EXPECT_EQ(false, message.packed_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.packed_enum(1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedClear(
+    const unittest::TestPackedTypesLite& message) {
+  // Packed repeated fields are empty.
+  EXPECT_EQ(0, message.packed_int32_size   ());
+  EXPECT_EQ(0, message.packed_int64_size   ());
+  EXPECT_EQ(0, message.packed_uint32_size  ());
+  EXPECT_EQ(0, message.packed_uint64_size  ());
+  EXPECT_EQ(0, message.packed_sint32_size  ());
+  EXPECT_EQ(0, message.packed_sint64_size  ());
+  EXPECT_EQ(0, message.packed_fixed32_size ());
+  EXPECT_EQ(0, message.packed_fixed64_size ());
+  EXPECT_EQ(0, message.packed_sfixed32_size());
+  EXPECT_EQ(0, message.packed_sfixed64_size());
+  EXPECT_EQ(0, message.packed_float_size   ());
+  EXPECT_EQ(0, message.packed_double_size  ());
+  EXPECT_EQ(0, message.packed_bool_size    ());
+  EXPECT_EQ(0, message.packed_enum_size    ());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedFieldsModified(
+    const unittest::TestPackedTypesLite& message) {
+  // Do the same for packed repeated fields.
+  ASSERT_EQ(2, message.packed_int32_size   ());
+  ASSERT_EQ(2, message.packed_int64_size   ());
+  ASSERT_EQ(2, message.packed_uint32_size  ());
+  ASSERT_EQ(2, message.packed_uint64_size  ());
+  ASSERT_EQ(2, message.packed_sint32_size  ());
+  ASSERT_EQ(2, message.packed_sint64_size  ());
+  ASSERT_EQ(2, message.packed_fixed32_size ());
+  ASSERT_EQ(2, message.packed_fixed64_size ());
+  ASSERT_EQ(2, message.packed_sfixed32_size());
+  ASSERT_EQ(2, message.packed_sfixed64_size());
+  ASSERT_EQ(2, message.packed_float_size   ());
+  ASSERT_EQ(2, message.packed_double_size  ());
+  ASSERT_EQ(2, message.packed_bool_size    ());
+  ASSERT_EQ(2, message.packed_enum_size    ());
+
+  EXPECT_EQ(601  , message.packed_int32   (0));
+  EXPECT_EQ(602  , message.packed_int64   (0));
+  EXPECT_EQ(603  , message.packed_uint32  (0));
+  EXPECT_EQ(604  , message.packed_uint64  (0));
+  EXPECT_EQ(605  , message.packed_sint32  (0));
+  EXPECT_EQ(606  , message.packed_sint64  (0));
+  EXPECT_EQ(607  , message.packed_fixed32 (0));
+  EXPECT_EQ(608  , message.packed_fixed64 (0));
+  EXPECT_EQ(609  , message.packed_sfixed32(0));
+  EXPECT_EQ(610  , message.packed_sfixed64(0));
+  EXPECT_EQ(611  , message.packed_float   (0));
+  EXPECT_EQ(612  , message.packed_double  (0));
+  EXPECT_EQ(true , message.packed_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0));
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(801  , message.packed_int32   (1));
+  EXPECT_EQ(802  , message.packed_int64   (1));
+  EXPECT_EQ(803  , message.packed_uint32  (1));
+  EXPECT_EQ(804  , message.packed_uint64  (1));
+  EXPECT_EQ(805  , message.packed_sint32  (1));
+  EXPECT_EQ(806  , message.packed_sint64  (1));
+  EXPECT_EQ(807  , message.packed_fixed32 (1));
+  EXPECT_EQ(808  , message.packed_fixed64 (1));
+  EXPECT_EQ(809  , message.packed_sfixed32(1));
+  EXPECT_EQ(810  , message.packed_sfixed64(1));
+  EXPECT_EQ(811  , message.packed_float   (1));
+  EXPECT_EQ(812  , message.packed_double  (1));
+  EXPECT_EQ(true , message.packed_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.packed_enum(1));
+}
+
+// ===================================================================
+// Extensions
+//
+// All this code is exactly equivalent to the above code except that it's
+// manipulating extension fields instead of normal ones.
+//
+// I gave up on the 80-char limit here.  Sorry.
+
+void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) {
+  message->SetExtension(unittest::optional_int32_extension_lite   , 101);
+  message->SetExtension(unittest::optional_int64_extension_lite   , 102);
+  message->SetExtension(unittest::optional_uint32_extension_lite  , 103);
+  message->SetExtension(unittest::optional_uint64_extension_lite  , 104);
+  message->SetExtension(unittest::optional_sint32_extension_lite  , 105);
+  message->SetExtension(unittest::optional_sint64_extension_lite  , 106);
+  message->SetExtension(unittest::optional_fixed32_extension_lite , 107);
+  message->SetExtension(unittest::optional_fixed64_extension_lite , 108);
+  message->SetExtension(unittest::optional_sfixed32_extension_lite, 109);
+  message->SetExtension(unittest::optional_sfixed64_extension_lite, 110);
+  message->SetExtension(unittest::optional_float_extension_lite   , 111);
+  message->SetExtension(unittest::optional_double_extension_lite  , 112);
+  message->SetExtension(unittest::optional_bool_extension_lite    , true);
+  message->SetExtension(unittest::optional_string_extension_lite  , "115");
+  message->SetExtension(unittest::optional_bytes_extension_lite   , "116");
+
+  message->MutableExtension(unittest::optionalgroup_extension_lite           )->set_a(117);
+  message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118);
+  message->MutableExtension(unittest::optional_foreign_message_extension_lite)->set_c(119);
+  message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120);
+
+  message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
+  message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ      );
+  message->SetExtension(unittest::optional_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->AddExtension(unittest::repeated_int32_extension_lite   , 201);
+  message->AddExtension(unittest::repeated_int64_extension_lite   , 202);
+  message->AddExtension(unittest::repeated_uint32_extension_lite  , 203);
+  message->AddExtension(unittest::repeated_uint64_extension_lite  , 204);
+  message->AddExtension(unittest::repeated_sint32_extension_lite  , 205);
+  message->AddExtension(unittest::repeated_sint64_extension_lite  , 206);
+  message->AddExtension(unittest::repeated_fixed32_extension_lite , 207);
+  message->AddExtension(unittest::repeated_fixed64_extension_lite , 208);
+  message->AddExtension(unittest::repeated_sfixed32_extension_lite, 209);
+  message->AddExtension(unittest::repeated_sfixed64_extension_lite, 210);
+  message->AddExtension(unittest::repeated_float_extension_lite   , 211);
+  message->AddExtension(unittest::repeated_double_extension_lite  , 212);
+  message->AddExtension(unittest::repeated_bool_extension_lite    , true);
+  message->AddExtension(unittest::repeated_string_extension_lite  , "215");
+  message->AddExtension(unittest::repeated_bytes_extension_lite   , "216");
+
+  message->AddExtension(unittest::repeatedgroup_extension_lite           )->set_a(217);
+  message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218);
+  message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219);
+  message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220);
+
+  message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR );
+  message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR      );
+  message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAR);
+
+
+  // Add a second one of each field.
+  message->AddExtension(unittest::repeated_int32_extension_lite   , 301);
+  message->AddExtension(unittest::repeated_int64_extension_lite   , 302);
+  message->AddExtension(unittest::repeated_uint32_extension_lite  , 303);
+  message->AddExtension(unittest::repeated_uint64_extension_lite  , 304);
+  message->AddExtension(unittest::repeated_sint32_extension_lite  , 305);
+  message->AddExtension(unittest::repeated_sint64_extension_lite  , 306);
+  message->AddExtension(unittest::repeated_fixed32_extension_lite , 307);
+  message->AddExtension(unittest::repeated_fixed64_extension_lite , 308);
+  message->AddExtension(unittest::repeated_sfixed32_extension_lite, 309);
+  message->AddExtension(unittest::repeated_sfixed64_extension_lite, 310);
+  message->AddExtension(unittest::repeated_float_extension_lite   , 311);
+  message->AddExtension(unittest::repeated_double_extension_lite  , 312);
+  message->AddExtension(unittest::repeated_bool_extension_lite    , false);
+  message->AddExtension(unittest::repeated_string_extension_lite  , "315");
+  message->AddExtension(unittest::repeated_bytes_extension_lite   , "316");
+
+  message->AddExtension(unittest::repeatedgroup_extension_lite           )->set_a(317);
+  message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318);
+  message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319);
+  message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320);
+
+  message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
+  message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ      );
+  message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->SetExtension(unittest::default_int32_extension_lite   , 401);
+  message->SetExtension(unittest::default_int64_extension_lite   , 402);
+  message->SetExtension(unittest::default_uint32_extension_lite  , 403);
+  message->SetExtension(unittest::default_uint64_extension_lite  , 404);
+  message->SetExtension(unittest::default_sint32_extension_lite  , 405);
+  message->SetExtension(unittest::default_sint64_extension_lite  , 406);
+  message->SetExtension(unittest::default_fixed32_extension_lite , 407);
+  message->SetExtension(unittest::default_fixed64_extension_lite , 408);
+  message->SetExtension(unittest::default_sfixed32_extension_lite, 409);
+  message->SetExtension(unittest::default_sfixed64_extension_lite, 410);
+  message->SetExtension(unittest::default_float_extension_lite   , 411);
+  message->SetExtension(unittest::default_double_extension_lite  , 412);
+  message->SetExtension(unittest::default_bool_extension_lite    , false);
+  message->SetExtension(unittest::default_string_extension_lite  , "415");
+  message->SetExtension(unittest::default_bytes_extension_lite   , "416");
+
+  message->SetExtension(unittest::default_nested_enum_extension_lite , unittest::TestAllTypesLite::FOO );
+  message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO      );
+  message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO);
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyRepeatedExtensions(
+    unittest::TestAllExtensionsLite* message) {
+  message->SetExtension(unittest::repeated_int32_extension_lite   , 1, 501);
+  message->SetExtension(unittest::repeated_int64_extension_lite   , 1, 502);
+  message->SetExtension(unittest::repeated_uint32_extension_lite  , 1, 503);
+  message->SetExtension(unittest::repeated_uint64_extension_lite  , 1, 504);
+  message->SetExtension(unittest::repeated_sint32_extension_lite  , 1, 505);
+  message->SetExtension(unittest::repeated_sint64_extension_lite  , 1, 506);
+  message->SetExtension(unittest::repeated_fixed32_extension_lite , 1, 507);
+  message->SetExtension(unittest::repeated_fixed64_extension_lite , 1, 508);
+  message->SetExtension(unittest::repeated_sfixed32_extension_lite, 1, 509);
+  message->SetExtension(unittest::repeated_sfixed64_extension_lite, 1, 510);
+  message->SetExtension(unittest::repeated_float_extension_lite   , 1, 511);
+  message->SetExtension(unittest::repeated_double_extension_lite  , 1, 512);
+  message->SetExtension(unittest::repeated_bool_extension_lite    , 1, true);
+  message->SetExtension(unittest::repeated_string_extension_lite  , 1, "515");
+  message->SetExtension(unittest::repeated_bytes_extension_lite   , 1, "516");
+
+  message->MutableExtension(unittest::repeatedgroup_extension_lite           , 1)->set_a(517);
+  message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518);
+  message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519);
+  message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520);
+
+  message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO );
+  message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO      );
+  message->SetExtension(unittest::repeated_import_enum_extension_lite , 1, unittest_import::IMPORT_LITE_FOO);
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectAllExtensionsSet(
+    const unittest::TestAllExtensionsLite& message) {
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite   ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite           ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+
+  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite           ).has_a());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  EXPECT_EQ(101  , message.GetExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_EQ(102  , message.GetExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_EQ(103  , message.GetExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_EQ(104  , message.GetExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_EQ(105  , message.GetExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_EQ(106  , message.GetExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_EQ(107  , message.GetExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_EQ(108  , message.GetExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_EQ(109  , message.GetExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_EQ(110  , message.GetExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_EQ(111  , message.GetExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_EQ(112  , message.GetExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_EQ(true , message.GetExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite   ));
+
+  EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite           ).a());
+  EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
+  EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite).c());
+  EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.GetExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
+
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension_lite   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension_lite   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension_lite   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0));
+
+
+  EXPECT_EQ(301  , message.GetExtension(unittest::repeated_int32_extension_lite   , 1));
+  EXPECT_EQ(302  , message.GetExtension(unittest::repeated_int64_extension_lite   , 1));
+  EXPECT_EQ(303  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 1));
+  EXPECT_EQ(304  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 1));
+  EXPECT_EQ(305  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 1));
+  EXPECT_EQ(306  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 1));
+  EXPECT_EQ(307  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1));
+  EXPECT_EQ(308  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1));
+  EXPECT_EQ(309  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1));
+  EXPECT_EQ(310  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1));
+  EXPECT_EQ(311  , message.GetExtension(unittest::repeated_float_extension_lite   , 1));
+  EXPECT_EQ(312  , message.GetExtension(unittest::repeated_double_extension_lite  , 1));
+  EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension_lite    , 1));
+  EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension_lite  , 1));
+  EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension_lite   , 1));
+
+  EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension_lite           , 1).a());
+  EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
+  EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
+  EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1));
+
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::default_float_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_double_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_string_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension_lite ));
+
+
+  EXPECT_EQ(401  , message.GetExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_EQ(402  , message.GetExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_EQ(403  , message.GetExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_EQ(404  , message.GetExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_EQ(405  , message.GetExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_EQ(406  , message.GetExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_EQ(407  , message.GetExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_EQ(408  , message.GetExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_EQ(409  , message.GetExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_EQ(410  , message.GetExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_EQ(411  , message.GetExtension(unittest::default_float_extension_lite   ));
+  EXPECT_EQ(412  , message.GetExtension(unittest::default_double_extension_lite  ));
+  EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension_lite  ));
+  EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite ));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectExtensionsClear(
+    const unittest::TestAllExtensionsLite& message) {
+  string serialized;
+  ASSERT_TRUE(message.SerializeToString(&serialized));
+  EXPECT_EQ("", serialized);
+  EXPECT_EQ(0, message.ByteSize());
+
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite   ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite           ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_EQ(false, message.GetExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_EQ(""   , message.GetExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_EQ(""   , message.GetExtension(unittest::optional_bytes_extension_lite   ));
+
+  // Embedded messages should also be clear.
+  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite           ).has_a());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+
+  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite           ).a());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite).c());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension_lite    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension_lite   ));
+
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension_lite           ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
+
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::default_float_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_double_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_string_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension_lite ));
+
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , message.GetExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_EQ( 42    , message.GetExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_EQ( 43    , message.GetExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_EQ( 44    , message.GetExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_EQ(-45    , message.GetExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_EQ( 46    , message.GetExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_EQ( 47    , message.GetExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_EQ( 48    , message.GetExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_EQ( 49    , message.GetExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_EQ(-50    , message.GetExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_EQ( 51.5  , message.GetExtension(unittest::default_float_extension_lite   ));
+  EXPECT_EQ( 52e3  , message.GetExtension(unittest::default_double_extension_lite  ));
+  EXPECT_EQ(true   , message.GetExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension_lite  ));
+  EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite ));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectRepeatedExtensionsModified(
+    const unittest::TestAllExtensionsLite& message) {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
+
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension_lite   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension_lite   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension_lite   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0));
+
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(501  , message.GetExtension(unittest::repeated_int32_extension_lite   , 1));
+  EXPECT_EQ(502  , message.GetExtension(unittest::repeated_int64_extension_lite   , 1));
+  EXPECT_EQ(503  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 1));
+  EXPECT_EQ(504  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 1));
+  EXPECT_EQ(505  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 1));
+  EXPECT_EQ(506  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 1));
+  EXPECT_EQ(507  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1));
+  EXPECT_EQ(508  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1));
+  EXPECT_EQ(509  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1));
+  EXPECT_EQ(510  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1));
+  EXPECT_EQ(511  , message.GetExtension(unittest::repeated_float_extension_lite   , 1));
+  EXPECT_EQ(512  , message.GetExtension(unittest::repeated_double_extension_lite  , 1));
+  EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite    , 1));
+  EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension_lite  , 1));
+  EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension_lite   , 1));
+
+  EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension_lite           , 1).a());
+  EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
+  EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
+  EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::SetPackedExtensions(
+    unittest::TestPackedExtensionsLite* message) {
+  message->AddExtension(unittest::packed_int32_extension_lite   , 601);
+  message->AddExtension(unittest::packed_int64_extension_lite   , 602);
+  message->AddExtension(unittest::packed_uint32_extension_lite  , 603);
+  message->AddExtension(unittest::packed_uint64_extension_lite  , 604);
+  message->AddExtension(unittest::packed_sint32_extension_lite  , 605);
+  message->AddExtension(unittest::packed_sint64_extension_lite  , 606);
+  message->AddExtension(unittest::packed_fixed32_extension_lite , 607);
+  message->AddExtension(unittest::packed_fixed64_extension_lite , 608);
+  message->AddExtension(unittest::packed_sfixed32_extension_lite, 609);
+  message->AddExtension(unittest::packed_sfixed64_extension_lite, 610);
+  message->AddExtension(unittest::packed_float_extension_lite   , 611);
+  message->AddExtension(unittest::packed_double_extension_lite  , 612);
+  message->AddExtension(unittest::packed_bool_extension_lite    , true);
+  message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAR);
+  // add a second one of each field
+  message->AddExtension(unittest::packed_int32_extension_lite   , 701);
+  message->AddExtension(unittest::packed_int64_extension_lite   , 702);
+  message->AddExtension(unittest::packed_uint32_extension_lite  , 703);
+  message->AddExtension(unittest::packed_uint64_extension_lite  , 704);
+  message->AddExtension(unittest::packed_sint32_extension_lite  , 705);
+  message->AddExtension(unittest::packed_sint64_extension_lite  , 706);
+  message->AddExtension(unittest::packed_fixed32_extension_lite , 707);
+  message->AddExtension(unittest::packed_fixed64_extension_lite , 708);
+  message->AddExtension(unittest::packed_sfixed32_extension_lite, 709);
+  message->AddExtension(unittest::packed_sfixed64_extension_lite, 710);
+  message->AddExtension(unittest::packed_float_extension_lite   , 711);
+  message->AddExtension(unittest::packed_double_extension_lite  , 712);
+  message->AddExtension(unittest::packed_bool_extension_lite    , false);
+  message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyPackedExtensions(
+    unittest::TestPackedExtensionsLite* message) {
+  message->SetExtension(unittest::packed_int32_extension_lite   , 1, 801);
+  message->SetExtension(unittest::packed_int64_extension_lite   , 1, 802);
+  message->SetExtension(unittest::packed_uint32_extension_lite  , 1, 803);
+  message->SetExtension(unittest::packed_uint64_extension_lite  , 1, 804);
+  message->SetExtension(unittest::packed_sint32_extension_lite  , 1, 805);
+  message->SetExtension(unittest::packed_sint64_extension_lite  , 1, 806);
+  message->SetExtension(unittest::packed_fixed32_extension_lite , 1, 807);
+  message->SetExtension(unittest::packed_fixed64_extension_lite , 1, 808);
+  message->SetExtension(unittest::packed_sfixed32_extension_lite, 1, 809);
+  message->SetExtension(unittest::packed_sfixed64_extension_lite, 1, 810);
+  message->SetExtension(unittest::packed_float_extension_lite   , 1, 811);
+  message->SetExtension(unittest::packed_double_extension_lite  , 1, 812);
+  message->SetExtension(unittest::packed_bool_extension_lite    , 1, true);
+  message->SetExtension(unittest::packed_enum_extension_lite    , 1,
+                        unittest::FOREIGN_LITE_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedExtensionsSet(
+    const unittest::TestPackedExtensionsLite& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite    ));
+
+  EXPECT_EQ(601  , message.GetExtension(unittest::packed_int32_extension_lite   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::packed_int64_extension_lite   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::packed_uint32_extension_lite  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::packed_uint64_extension_lite  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::packed_sint32_extension_lite  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::packed_sint64_extension_lite  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::packed_fixed32_extension_lite , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::packed_fixed64_extension_lite , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::packed_float_extension_lite   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::packed_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite    , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR,
+            message.GetExtension(unittest::packed_enum_extension_lite, 0));
+  EXPECT_EQ(701  , message.GetExtension(unittest::packed_int32_extension_lite   , 1));
+  EXPECT_EQ(702  , message.GetExtension(unittest::packed_int64_extension_lite   , 1));
+  EXPECT_EQ(703  , message.GetExtension(unittest::packed_uint32_extension_lite  , 1));
+  EXPECT_EQ(704  , message.GetExtension(unittest::packed_uint64_extension_lite  , 1));
+  EXPECT_EQ(705  , message.GetExtension(unittest::packed_sint32_extension_lite  , 1));
+  EXPECT_EQ(706  , message.GetExtension(unittest::packed_sint64_extension_lite  , 1));
+  EXPECT_EQ(707  , message.GetExtension(unittest::packed_fixed32_extension_lite , 1));
+  EXPECT_EQ(708  , message.GetExtension(unittest::packed_fixed64_extension_lite , 1));
+  EXPECT_EQ(709  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1));
+  EXPECT_EQ(710  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1));
+  EXPECT_EQ(711  , message.GetExtension(unittest::packed_float_extension_lite   , 1));
+  EXPECT_EQ(712  , message.GetExtension(unittest::packed_double_extension_lite  , 1));
+  EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension_lite    , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ,
+            message.GetExtension(unittest::packed_enum_extension_lite, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedExtensionsClear(
+    const unittest::TestPackedExtensionsLite& message) {
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension_lite    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension_lite    ));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedExtensionsModified(
+    const unittest::TestPackedExtensionsLite& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite    ));
+  EXPECT_EQ(601  , message.GetExtension(unittest::packed_int32_extension_lite   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::packed_int64_extension_lite   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::packed_uint32_extension_lite  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::packed_uint64_extension_lite  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::packed_sint32_extension_lite  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::packed_sint64_extension_lite  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::packed_fixed32_extension_lite , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::packed_fixed64_extension_lite , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::packed_float_extension_lite   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::packed_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite    , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR,
+            message.GetExtension(unittest::packed_enum_extension_lite, 0));
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(801  , message.GetExtension(unittest::packed_int32_extension_lite   , 1));
+  EXPECT_EQ(802  , message.GetExtension(unittest::packed_int64_extension_lite   , 1));
+  EXPECT_EQ(803  , message.GetExtension(unittest::packed_uint32_extension_lite  , 1));
+  EXPECT_EQ(804  , message.GetExtension(unittest::packed_uint64_extension_lite  , 1));
+  EXPECT_EQ(805  , message.GetExtension(unittest::packed_sint32_extension_lite  , 1));
+  EXPECT_EQ(806  , message.GetExtension(unittest::packed_sint64_extension_lite  , 1));
+  EXPECT_EQ(807  , message.GetExtension(unittest::packed_fixed32_extension_lite , 1));
+  EXPECT_EQ(808  , message.GetExtension(unittest::packed_fixed64_extension_lite , 1));
+  EXPECT_EQ(809  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1));
+  EXPECT_EQ(810  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1));
+  EXPECT_EQ(811  , message.GetExtension(unittest::packed_float_extension_lite   , 1));
+  EXPECT_EQ(812  , message.GetExtension(unittest::packed_double_extension_lite  , 1));
+  EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite    , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO,
+            message.GetExtension(unittest::packed_enum_extension_lite, 1));
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/test_util_lite.h b/src/google/protobuf/test_util_lite.h
new file mode 100644
index 0000000..ca35aaa
--- /dev/null
+++ b/src/google/protobuf/test_util_lite.h
@@ -0,0 +1,101 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
+#define GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
+
+#include <google/protobuf/unittest_lite.pb.h>
+
+namespace google {
+namespace protobuf {
+
+namespace unittest = protobuf_unittest;
+namespace unittest_import = protobuf_unittest_import;
+
+class TestUtilLite {
+ public:
+  // Set every field in the message to a unique value.
+  static void SetAllFields(unittest::TestAllTypesLite* message);
+  static void SetAllExtensions(unittest::TestAllExtensionsLite* message);
+  static void SetPackedFields(unittest::TestPackedTypesLite* message);
+  static void SetPackedExtensions(unittest::TestPackedExtensionsLite* message);
+
+  // Use the repeated versions of the set_*() accessors to modify all the
+  // repeated fields of the messsage (which should already have been
+  // initialized with Set*Fields()).  Set*Fields() itself only tests
+  // the add_*() accessors.
+  static void ModifyRepeatedFields(unittest::TestAllTypesLite* message);
+  static void ModifyRepeatedExtensions(
+      unittest::TestAllExtensionsLite* message);
+  static void ModifyPackedFields(unittest::TestPackedTypesLite* message);
+  static void ModifyPackedExtensions(
+      unittest::TestPackedExtensionsLite* message);
+
+  // Check that all fields have the values that they should have after
+  // Set*Fields() is called.
+  static void ExpectAllFieldsSet(const unittest::TestAllTypesLite& message);
+  static void ExpectAllExtensionsSet(
+      const unittest::TestAllExtensionsLite& message);
+  static void ExpectPackedFieldsSet(
+      const unittest::TestPackedTypesLite& message);
+  static void ExpectPackedExtensionsSet(
+      const unittest::TestPackedExtensionsLite& message);
+
+  // Expect that the message is modified as would be expected from
+  // Modify*Fields().
+  static void ExpectRepeatedFieldsModified(
+      const unittest::TestAllTypesLite& message);
+  static void ExpectRepeatedExtensionsModified(
+      const unittest::TestAllExtensionsLite& message);
+  static void ExpectPackedFieldsModified(
+      const unittest::TestPackedTypesLite& message);
+  static void ExpectPackedExtensionsModified(
+      const unittest::TestPackedExtensionsLite& message);
+
+  // Check that all fields have their default values.
+  static void ExpectClear(const unittest::TestAllTypesLite& message);
+  static void ExpectExtensionsClear(
+      const unittest::TestAllExtensionsLite& message);
+  static void ExpectPackedClear(const unittest::TestPackedTypesLite& message);
+  static void ExpectPackedExtensionsClear(
+      const unittest::TestPackedExtensionsLite& message);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtilLite);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index ae88cdf..cf75402 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -142,6 +142,16 @@
     }
   }
 
+  bool ParseField(const FieldDescriptor* field, Message* output) {
+    bool suc;
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      suc = ConsumeFieldMessage(output, output->GetReflection(), field);
+    } else {
+      suc = ConsumeFieldValue(output, output->GetReflection(), field);
+    }
+    return suc && LookingAtType(io::Tokenizer::TYPE_END);
+  }
+
   void ReportError(int line, int col, const string& message) {
     had_errors_ = true;
     if (error_collector_ == NULL) {
@@ -252,24 +262,9 @@
 
     // Perform special handling for embedded message types.
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      string delimeter;
-
       // ':' is optional here.
       TryConsume(":");
-
-      if (TryConsume("<")) {
-        delimeter = ">";
-      } else {
-        DO(Consume("{"));
-        delimeter = "}";
-      }
-
-      if (field->is_repeated()) {
-        DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter));
-      } else {
-        DO(ConsumeMessage(reflection->MutableMessage(message, field),
-                          delimeter));
-      }
+      DO(ConsumeFieldMessage(message, reflection, field));
     } else {
       DO(Consume(":"));
       DO(ConsumeFieldValue(message, reflection, field));
@@ -278,6 +273,26 @@
     return true;
   }
 
+  bool ConsumeFieldMessage(Message* message,
+                           const Reflection* reflection,
+                           const FieldDescriptor* field) {
+    string delimeter;
+    if (TryConsume("<")) {
+      delimeter = ">";
+    } else {
+      DO(Consume("{"));
+      delimeter = "}";
+    }
+
+    if (field->is_repeated()) {
+      DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter));
+    } else {
+      DO(ConsumeMessage(reflection->MutableMessage(message, field),
+                        delimeter));
+    }
+    return true;
+  }
+
   bool ConsumeFieldValue(Message* message,
                          const Reflection* reflection,
                          const FieldDescriptor* field) {
@@ -750,6 +765,16 @@
   return true;
 }
 
+bool TextFormat::Parser::ParseFieldValueFromString(
+    const string& input,
+    const FieldDescriptor* field,
+    Message* output) {
+  io::ArrayInputStream input_stream(input.data(), input.size());
+  ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
+                    ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+  return parser.ParseField(field, output);
+}
+
 /* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input,
                                     Message* output) {
   return Parser().Parse(input, output);
@@ -1008,6 +1033,13 @@
   return Printer().PrintFieldValueToString(message, field, index, output);
 }
 
+/* static */ bool TextFormat::ParseFieldValueFromString(
+    const string& input,
+    const FieldDescriptor* field,
+    Message* message) {
+  return Parser().ParseFieldValueFromString(input, field, message);
+}
+
 // Prints an integer as hex with a fixed number of digits dependent on the
 // integer type.
 template<typename IntType>
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index e2b27c6..39a039d 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -165,6 +165,13 @@
   // Like Merge(), but reads directly from a string.
   static bool MergeFromString(const string& input, Message* output);
 
+  // Parse the given text as a single field value and store it into the
+  // given field of the given message. If the field is a repeated field,
+  // the new value will be added to the end
+  static bool ParseFieldValueFromString(const string& input,
+                                        const FieldDescriptor* field,
+                                        Message* message);
+
   // For more control over parsing, use this class.
   class LIBPROTOBUF_EXPORT Parser {
    public:
@@ -192,6 +199,11 @@
       allow_partial_ = allow;
     }
 
+    // Like TextFormat::ParseFieldValueFromString
+    bool ParseFieldValueFromString(const string& input,
+                                   const FieldDescriptor* field,
+                                   Message* output);
+
    private:
     // Forward declaration of an internal class used to parse text
     // representations (see text_format.cc for implementation).
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index eaa278b..7c31e80 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -597,8 +597,8 @@
  protected:
   void ExpectFailure(const string& input, const string& message, int line,
                      int col) {
-    unittest::TestAllTypes proto;
-    ExpectFailure(input, message, line, col, &proto);
+    scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
+    ExpectFailure(input, message, line, col, proto.get());
   }
 
   void ExpectFailure(const string& input, const string& message, int line,
@@ -628,6 +628,120 @@
   };
 };
 
+TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
+  scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+  const Descriptor* d = message->GetDescriptor();
+
+#define EXPECT_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_EQ(value, message->optional_##name()); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_FLOAT_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_FLOAT_EQ(value, message->optional_##name()); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_DOUBLE_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_DOUBLE_EQ(value, message->optional_##name()); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_INVALID(name, valuestring) \
+  EXPECT_FALSE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get()));
+
+  // int32
+  EXPECT_FIELD(int32, 1, "1");
+  EXPECT_FIELD(int32, -1, "-1");
+  EXPECT_FIELD(int32, 0x1234, "0x1234");
+  EXPECT_INVALID(int32, "a");
+  EXPECT_INVALID(int32, "999999999999999999999999999999999999");
+  EXPECT_INVALID(int32, "1,2");
+
+  // int64
+  EXPECT_FIELD(int64, 1, "1");
+  EXPECT_FIELD(int64, -1, "-1");
+  EXPECT_FIELD(int64, 0x1234567812345678LL, "0x1234567812345678");
+  EXPECT_INVALID(int64, "a");
+  EXPECT_INVALID(int64, "999999999999999999999999999999999999");
+  EXPECT_INVALID(int64, "1,2");
+
+  // uint64
+  EXPECT_FIELD(uint64, 1, "1");
+  EXPECT_FIELD(uint64, 0xf234567812345678ULL, "0xf234567812345678");
+  EXPECT_INVALID(uint64, "-1");
+  EXPECT_INVALID(uint64, "a");
+  EXPECT_INVALID(uint64, "999999999999999999999999999999999999");
+  EXPECT_INVALID(uint64, "1,2");
+
+  // fixed32
+  EXPECT_FIELD(fixed32, 1, "1");
+  EXPECT_FIELD(fixed32, 0x12345678, "0x12345678");
+  EXPECT_INVALID(fixed32, "-1");
+  EXPECT_INVALID(fixed32, "a");
+  EXPECT_INVALID(fixed32, "999999999999999999999999999999999999");
+  EXPECT_INVALID(fixed32, "1,2");
+
+  // fixed64
+  EXPECT_FIELD(fixed64, 1, "1");
+  EXPECT_FIELD(fixed64, 0x1234567812345678ULL, "0x1234567812345678");
+  EXPECT_INVALID(fixed64, "-1");
+  EXPECT_INVALID(fixed64, "a");
+  EXPECT_INVALID(fixed64, "999999999999999999999999999999999999");
+  EXPECT_INVALID(fixed64, "1,2");
+
+  // bool
+  EXPECT_FIELD(bool, true, "true");
+  EXPECT_FIELD(bool, false, "false");
+  EXPECT_INVALID(bool, "1");
+  EXPECT_INVALID(bool, "on");
+  EXPECT_INVALID(bool, "a");
+  EXPECT_INVALID(bool, "True");
+
+  // float
+  EXPECT_FIELD(float, 1, "1");
+  EXPECT_FLOAT_FIELD(float, 1.5, "1.5");
+  EXPECT_FLOAT_FIELD(float, 1.5e3, "1.5e3");
+  EXPECT_FLOAT_FIELD(float, -4.55, "-4.55");
+  EXPECT_INVALID(float, "a");
+  EXPECT_INVALID(float, "1,2");
+
+  // double
+  EXPECT_FIELD(double, 1, "1");
+  EXPECT_FIELD(double, -1, "-1");
+  EXPECT_DOUBLE_FIELD(double, 2.3, "2.3");
+  EXPECT_DOUBLE_FIELD(double, 3e5, "3e5");
+  EXPECT_INVALID(double, "a");
+  EXPECT_INVALID(double, "1,2");
+
+  // string
+  EXPECT_FIELD(string, "hello", "\"hello\"");
+  EXPECT_FIELD(string, "-1.87", "'-1.87'");
+  EXPECT_INVALID(string, "hello");  // without quote for value
+
+  // enum
+  EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR");
+  EXPECT_INVALID(nested_enum, "1");  // number not supported
+  EXPECT_INVALID(nested_enum, "FOOBAR");
+
+  // message
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString(
+    "<bb:12>", d->FindFieldByName("optional_nested_message"), message.get()));
+  EXPECT_EQ(12, message->optional_nested_message().bb()); \
+  EXPECT_TRUE(message->has_optional_nested_message());
+  EXPECT_INVALID(nested_message, "any");
+
+#undef EXPECT_FIELD
+#undef EXPECT_FLOAT_FIELD
+#undef EXPECT_DOUBLE_FIELD
+#undef EXPECT_INVALID
+}
+
+
 TEST_F(TextFormatParserTest, InvalidToken) {
   ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.",
                 2, 1);
@@ -735,7 +849,7 @@
       "Unknown enumeration value of \"grah\" for field "
       "\"optional_nested_enum\".", 2, 1);
 
- ExpectFailure(
+  ExpectFailure(
       "optional_nested_enum {\n \n}\n",
       "Expected \":\", found \"{\".", 1, 22);
 }
diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto
index 88f6f1f..b6ee03d 100644
--- a/src/google/protobuf/unittest_custom_options.proto
+++ b/src/google/protobuf/unittest_custom_options.proto
@@ -204,6 +204,8 @@
 
 message ComplexOptionType1 {
   optional int32 foo = 1;
+  optional int32 foo2 = 2;
+  optional int32 foo3 = 3;
 
   extensions 100 to max;
 }
diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto
new file mode 100644
index 0000000..ebaab5c
--- /dev/null
+++ b/src/google/protobuf/unittest_import_lite.proto
@@ -0,0 +1,49 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+message ImportMessageLite {
+  optional int32 d = 1;
+}
+
+enum ImportEnumLite {
+  IMPORT_LITE_FOO = 7;
+  IMPORT_LITE_BAR = 8;
+  IMPORT_LITE_BAZ = 9;
+}
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
new file mode 100644
index 0000000..cca6b49
--- /dev/null
+++ b/src/google/protobuf/unittest_lite.proto
@@ -0,0 +1,312 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest_import_lite.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+// Same as TestAllTypes but with the lite runtime.
+message TestAllTypesLite {
+  message NestedMessage {
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  // Singular
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional NestedMessage      optional_nested_message  = 18;
+  optional ForeignMessageLite optional_foreign_message = 19;
+  optional protobuf_unittest_import.ImportMessageLite
+    optional_import_message = 20;
+
+  optional NestedEnum      optional_nested_enum     = 21;
+  optional ForeignEnumLite optional_foreign_enum    = 22;
+  optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated NestedMessage      repeated_nested_message  = 48;
+  repeated ForeignMessageLite repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessageLite
+    repeated_import_message = 50;
+
+  repeated NestedEnum      repeated_nested_enum  = 51;
+  repeated ForeignEnumLite repeated_foreign_enum = 52;
+  repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  // Singular with defaults
+  optional    int32 default_int32    = 61 [default =  41    ];
+  optional    int64 default_int64    = 62 [default =  42    ];
+  optional   uint32 default_uint32   = 63 [default =  43    ];
+  optional   uint64 default_uint64   = 64 [default =  44    ];
+  optional   sint32 default_sint32   = 65 [default = -45    ];
+  optional   sint64 default_sint64   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
+  optional    float default_float    = 71 [default =  51.5  ];
+  optional   double default_double   = 72 [default =  52e3  ];
+  optional     bool default_bool     = 73 [default = true   ];
+  optional   string default_string   = 74 [default = "hello"];
+  optional    bytes default_bytes    = 75 [default = "world"];
+
+  optional NestedEnum default_nested_enum = 81 [default = BAR];
+  optional ForeignEnumLite default_foreign_enum = 82
+      [default = FOREIGN_LITE_BAR];
+  optional protobuf_unittest_import.ImportEnumLite
+      default_import_enum = 83 [default = IMPORT_LITE_BAR];
+
+  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+  optional string default_cord = 85 [ctype=CORD,default="123"];
+}
+
+message ForeignMessageLite {
+  optional int32 c = 1;
+}
+
+enum ForeignEnumLite {
+  FOREIGN_LITE_FOO = 4;
+  FOREIGN_LITE_BAR = 5;
+  FOREIGN_LITE_BAZ = 6;
+}
+
+message TestPackedTypesLite {
+  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 ForeignEnumLite packed_enum  = 103 [packed = true];
+}
+
+message TestAllExtensionsLite {
+  extensions 1 to max;
+}
+
+extend TestAllExtensionsLite {
+  // Singular
+  optional    int32 optional_int32_extension_lite    =  1;
+  optional    int64 optional_int64_extension_lite    =  2;
+  optional   uint32 optional_uint32_extension_lite   =  3;
+  optional   uint64 optional_uint64_extension_lite   =  4;
+  optional   sint32 optional_sint32_extension_lite   =  5;
+  optional   sint64 optional_sint64_extension_lite   =  6;
+  optional  fixed32 optional_fixed32_extension_lite  =  7;
+  optional  fixed64 optional_fixed64_extension_lite  =  8;
+  optional sfixed32 optional_sfixed32_extension_lite =  9;
+  optional sfixed64 optional_sfixed64_extension_lite = 10;
+  optional    float optional_float_extension_lite    = 11;
+  optional   double optional_double_extension_lite   = 12;
+  optional     bool optional_bool_extension_lite     = 13;
+  optional   string optional_string_extension_lite   = 14;
+  optional    bytes optional_bytes_extension_lite    = 15;
+
+  optional group OptionalGroup_extension_lite = 16 {
+    optional int32 a = 17;
+  }
+
+  optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite
+      = 18;
+  optional ForeignMessageLite optional_foreign_message_extension_lite = 19;
+  optional protobuf_unittest_import.ImportMessageLite
+    optional_import_message_extension_lite = 20;
+
+  optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21;
+  optional ForeignEnumLite optional_foreign_enum_extension_lite = 22;
+  optional protobuf_unittest_import.ImportEnumLite
+    optional_import_enum_extension_lite = 23;
+
+  optional string optional_string_piece_extension_lite = 24
+      [ctype=STRING_PIECE];
+  optional string optional_cord_extension_lite = 25 [ctype=CORD];
+
+  // Repeated
+  repeated    int32 repeated_int32_extension_lite    = 31;
+  repeated    int64 repeated_int64_extension_lite    = 32;
+  repeated   uint32 repeated_uint32_extension_lite   = 33;
+  repeated   uint64 repeated_uint64_extension_lite   = 34;
+  repeated   sint32 repeated_sint32_extension_lite   = 35;
+  repeated   sint64 repeated_sint64_extension_lite   = 36;
+  repeated  fixed32 repeated_fixed32_extension_lite  = 37;
+  repeated  fixed64 repeated_fixed64_extension_lite  = 38;
+  repeated sfixed32 repeated_sfixed32_extension_lite = 39;
+  repeated sfixed64 repeated_sfixed64_extension_lite = 40;
+  repeated    float repeated_float_extension_lite    = 41;
+  repeated   double repeated_double_extension_lite   = 42;
+  repeated     bool repeated_bool_extension_lite     = 43;
+  repeated   string repeated_string_extension_lite   = 44;
+  repeated    bytes repeated_bytes_extension_lite    = 45;
+
+  repeated group RepeatedGroup_extension_lite = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite
+      = 48;
+  repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49;
+  repeated protobuf_unittest_import.ImportMessageLite
+    repeated_import_message_extension_lite = 50;
+
+  repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51;
+  repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52;
+  repeated protobuf_unittest_import.ImportEnumLite
+    repeated_import_enum_extension_lite = 53;
+
+  repeated string repeated_string_piece_extension_lite = 54
+      [ctype=STRING_PIECE];
+  repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
+
+  // Singular with defaults
+  optional    int32 default_int32_extension_lite    = 61 [default =  41    ];
+  optional    int64 default_int64_extension_lite    = 62 [default =  42    ];
+  optional   uint32 default_uint32_extension_lite   = 63 [default =  43    ];
+  optional   uint64 default_uint64_extension_lite   = 64 [default =  44    ];
+  optional   sint32 default_sint32_extension_lite   = 65 [default = -45    ];
+  optional   sint64 default_sint64_extension_lite   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32_extension_lite  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64_extension_lite  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32_extension_lite = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50    ];
+  optional    float default_float_extension_lite    = 71 [default =  51.5  ];
+  optional   double default_double_extension_lite   = 72 [default =  52e3  ];
+  optional     bool default_bool_extension_lite     = 73 [default = true   ];
+  optional   string default_string_extension_lite   = 74 [default = "hello"];
+  optional    bytes default_bytes_extension_lite    = 75 [default = "world"];
+
+  optional TestAllTypesLite.NestedEnum
+    default_nested_enum_extension_lite = 81 [default = BAR];
+  optional ForeignEnumLite
+    default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR];
+  optional protobuf_unittest_import.ImportEnumLite
+    default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR];
+
+  optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE,
+                                                            default="abc"];
+  optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"];
+}
+
+message TestPackedExtensionsLite {
+  extensions 1 to max;
+}
+
+extend TestPackedExtensionsLite {
+  repeated    int32 packed_int32_extension_lite    =  90 [packed = true];
+  repeated    int64 packed_int64_extension_lite    =  91 [packed = true];
+  repeated   uint32 packed_uint32_extension_lite   =  92 [packed = true];
+  repeated   uint64 packed_uint64_extension_lite   =  93 [packed = true];
+  repeated   sint32 packed_sint32_extension_lite   =  94 [packed = true];
+  repeated   sint64 packed_sint64_extension_lite   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32_extension_lite  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64_extension_lite  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32_extension_lite =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64_extension_lite =  99 [packed = true];
+  repeated    float packed_float_extension_lite    = 100 [packed = true];
+  repeated   double packed_double_extension_lite   = 101 [packed = true];
+  repeated     bool packed_bool_extension_lite     = 102 [packed = true];
+  repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true];
+}
+
+message TestNestedExtensionLite {
+  extend TestAllExtensionsLite {
+    optional int32 nested_extension = 12345;
+  }
+}
+
+// Test that deprecated fields work.  We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedLite {
+  optional int32 deprecated_field = 1 [deprecated = true];
+}
diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto
new file mode 100644
index 0000000..d52cb8c
--- /dev/null
+++ b/src/google/protobuf/unittest_lite_imports_nonlite.proto
@@ -0,0 +1,43 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Tests that a "lite" message can import a regular message.
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+message TestLiteImportsNonlite {
+  optional TestAllTypes message = 1;
+}
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index dbd39b8..5aa6772 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -36,20 +36,24 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format.h>
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/unknown_field_set.h>
 
+
 namespace google {
 namespace protobuf {
 namespace internal {
 
+using internal::WireFormatLite;
+
 namespace {
 
 // This function turns out to be convenient when using some macros later.
@@ -57,74 +61,42 @@
   return descriptor->number();
 }
 
-// These are the tags for the old MessageSet format, which was defined as:
-//   message MessageSet {
-//     repeated group Item = 1 {
-//       required int32 type_id = 2;
-//       required string message = 3;
-//     }
-//   }
-const int kMessageSetItemStartTag =
-  GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormat::WIRETYPE_START_GROUP);
-const int kMessageSetItemEndTag =
-  GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormat::WIRETYPE_END_GROUP);
-const int kMessageSetTypeIdTag =
-  GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(2, WireFormat::WIRETYPE_VARINT);
-const int kMessageSetMessageTag =
-  GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(3, WireFormat::WIRETYPE_LENGTH_DELIMITED);
-
-// Byte size of all tags of a MessageSet::Item combined.
-static const int kMessageSetItemTagsSize =
-  io::CodedOutputStream::VarintSize32(kMessageSetItemStartTag) +
-  io::CodedOutputStream::VarintSize32(kMessageSetItemEndTag) +
-  io::CodedOutputStream::VarintSize32(kMessageSetTypeIdTag) +
-  io::CodedOutputStream::VarintSize32(kMessageSetMessageTag);
-
 }  // anonymous namespace
 
-const WireFormat::WireType
-WireFormat::kWireTypeForFieldType[FieldDescriptor::MAX_TYPE + 1] = {
-  static_cast<WireFormat::WireType>(-1),  // invalid
-  WIRETYPE_FIXED64,           // TYPE_DOUBLE
-  WIRETYPE_FIXED32,           // TYPE_FLOAT
-  WIRETYPE_VARINT,            // TYPE_INT64
-  WIRETYPE_VARINT,            // TYPE_UINT64
-  WIRETYPE_VARINT,            // TYPE_INT32
-  WIRETYPE_FIXED64,           // TYPE_FIXED64
-  WIRETYPE_FIXED32,           // TYPE_FIXED32
-  WIRETYPE_VARINT,            // TYPE_BOOL
-  WIRETYPE_LENGTH_DELIMITED,  // TYPE_STRING
-  WIRETYPE_START_GROUP,       // TYPE_GROUP
-  WIRETYPE_LENGTH_DELIMITED,  // TYPE_MESSAGE
-  WIRETYPE_LENGTH_DELIMITED,  // TYPE_BYTES
-  WIRETYPE_VARINT,            // TYPE_UINT32
-  WIRETYPE_VARINT,            // TYPE_ENUM
-  WIRETYPE_FIXED32,           // TYPE_SFIXED32
-  WIRETYPE_FIXED64,           // TYPE_SFIXED64
-  WIRETYPE_VARINT,            // TYPE_SINT32
-  WIRETYPE_VARINT,            // TYPE_SINT64
-};
-
 // ===================================================================
 
+bool UnknownFieldSetFieldSkipper::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  return WireFormat::SkipField(input, tag, unknown_fields_);
+}
+
+bool UnknownFieldSetFieldSkipper::SkipMessage(io::CodedInputStream* input) {
+  return WireFormat::SkipMessage(input, unknown_fields_);
+}
+
+void UnknownFieldSetFieldSkipper::SkipUnknownEnum(
+    int field_number, int value) {
+  unknown_fields_->AddVarint(field_number, value);
+}
+
 bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
                            UnknownFieldSet* unknown_fields) {
-  int number = GetTagFieldNumber(tag);
+  int number = WireFormatLite::GetTagFieldNumber(tag);
 
-  switch (GetTagWireType(tag)) {
-    case WIRETYPE_VARINT: {
+  switch (WireFormatLite::GetTagWireType(tag)) {
+    case WireFormatLite::WIRETYPE_VARINT: {
       uint64 value;
       if (!input->ReadVarint64(&value)) return false;
       if (unknown_fields != NULL) unknown_fields->AddVarint(number, value);
       return true;
     }
-    case WIRETYPE_FIXED64: {
+    case WireFormatLite::WIRETYPE_FIXED64: {
       uint64 value;
       if (!input->ReadLittleEndian64(&value)) return false;
       if (unknown_fields != NULL) unknown_fields->AddFixed64(number, value);
       return true;
     }
-    case WIRETYPE_LENGTH_DELIMITED: {
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
       uint32 length;
       if (!input->ReadVarint32(&length)) return false;
       if (unknown_fields == NULL) {
@@ -137,7 +109,7 @@
       }
       return true;
     }
-    case WIRETYPE_START_GROUP: {
+    case WireFormatLite::WIRETYPE_START_GROUP: {
       if (!input->IncrementRecursionDepth()) return false;
       if (!SkipMessage(input, (unknown_fields == NULL) ?
                               NULL : unknown_fields->AddGroup(number))) {
@@ -145,16 +117,17 @@
       }
       input->DecrementRecursionDepth();
       // Check that the ending tag matched the starting tag.
-      if (!input->LastTagWas(
-          MakeTag(GetTagFieldNumber(tag), WIRETYPE_END_GROUP))) {
+      if (!input->LastTagWas(WireFormatLite::MakeTag(
+          WireFormatLite::GetTagFieldNumber(tag),
+          WireFormatLite::WIRETYPE_END_GROUP))) {
         return false;
       }
       return true;
     }
-    case WIRETYPE_END_GROUP: {
+    case WireFormatLite::WIRETYPE_END_GROUP: {
       return false;
     }
-    case WIRETYPE_FIXED32: {
+    case WireFormatLite::WIRETYPE_FIXED32: {
       uint32 value;
       if (!input->ReadLittleEndian32(&value)) return false;
       if (unknown_fields != NULL) unknown_fields->AddFixed32(number, value);
@@ -175,9 +148,9 @@
       return true;
     }
 
-    WireType wire_type = GetTagWireType(tag);
+    WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
 
-    if (wire_type == WIRETYPE_END_GROUP) {
+    if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
       // Must be the end of the message.
       return true;
     }
@@ -192,27 +165,32 @@
     const UnknownField& field = unknown_fields.field(i);
     switch (field.type()) {
       case UnknownField::TYPE_VARINT:
-        output->WriteVarint32(MakeTag(field.number(), WIRETYPE_VARINT));
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_VARINT));
         output->WriteVarint64(field.varint());
         break;
       case UnknownField::TYPE_FIXED32:
-        output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED32));
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED32));
         output->WriteLittleEndian32(field.fixed32());
         break;
       case UnknownField::TYPE_FIXED64:
-        output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED64));
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED64));
         output->WriteLittleEndian64(field.fixed64());
         break;
       case UnknownField::TYPE_LENGTH_DELIMITED:
-        output->WriteVarint32(
-            MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED));
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
         output->WriteVarint32(field.length_delimited().size());
         output->WriteString(field.length_delimited());
         break;
       case UnknownField::TYPE_GROUP:
-        output->WriteVarint32(MakeTag(field.number(),WIRETYPE_START_GROUP));
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_START_GROUP));
         SerializeUnknownFields(field.group(), output);
-        output->WriteVarint32(MakeTag(field.number(), WIRETYPE_END_GROUP));
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_END_GROUP));
         break;
     }
   }
@@ -226,22 +204,27 @@
 
     switch (field.type()) {
       case UnknownField::TYPE_VARINT:
-        target = WriteInt64ToArray(field.number(), field.varint(), target);
+        target = WireFormatLite::WriteInt64ToArray(
+            field.number(), field.varint(), target);
         break;
       case UnknownField::TYPE_FIXED32:
-        target = WriteFixed32ToArray(field.number(), field.fixed32(), target);
+        target = WireFormatLite::WriteFixed32ToArray(
+            field.number(), field.fixed32(), target);
         break;
       case UnknownField::TYPE_FIXED64:
-        target = WriteFixed64ToArray(field.number(), field.fixed64(), target);
+        target = WireFormatLite::WriteFixed64ToArray(
+            field.number(), field.fixed64(), target);
         break;
       case UnknownField::TYPE_LENGTH_DELIMITED:
-        target =
-          WriteBytesToArray(field.number(), field.length_delimited(), target);
+        target = WireFormatLite::WriteBytesToArray(
+            field.number(), field.length_delimited(), target);
         break;
       case UnknownField::TYPE_GROUP:
-        target = WriteTagToArray(field.number(), WIRETYPE_START_GROUP, target);
+        target = WireFormatLite::WriteTagToArray(
+            field.number(), WireFormatLite::WIRETYPE_START_GROUP, target);
         target = SerializeUnknownFieldsToArray(field.group(), target);
-        target = WriteTagToArray(field.number(), WIRETYPE_END_GROUP, target);
+        target = WireFormatLite::WriteTagToArray(
+            field.number(), WireFormatLite::WIRETYPE_END_GROUP, target);
         break;
     }
   }
@@ -259,19 +242,19 @@
       const string& data = field.length_delimited();
 
       // Start group.
-      output->WriteVarint32(kMessageSetItemStartTag);
+      output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
 
       // Write type ID.
-      output->WriteVarint32(kMessageSetTypeIdTag);
+      output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
       output->WriteVarint32(field.number());
 
       // Write message.
-      output->WriteVarint32(kMessageSetMessageTag);
+      output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
       output->WriteVarint32(data.size());
       output->WriteString(data);
 
       // End group.
-      output->WriteVarint32(kMessageSetItemEndTag);
+      output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
     }
   }
 }
@@ -288,24 +271,24 @@
       const string& data = field.length_delimited();
 
       // Start group.
-      target =
-        io::CodedOutputStream::WriteTagToArray(kMessageSetItemStartTag, target);
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetItemStartTag, target);
 
       // Write type ID.
-      target =
-        io::CodedOutputStream::WriteTagToArray(kMessageSetTypeIdTag, target);
-      target =
-        io::CodedOutputStream::WriteVarint32ToArray(field.number(), target);
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetTypeIdTag, target);
+      target = io::CodedOutputStream::WriteVarint32ToArray(
+          field.number(), target);
 
       // Write message.
-      target =
-        io::CodedOutputStream::WriteTagToArray(kMessageSetMessageTag, target);
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetMessageTag, target);
       target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
       target = io::CodedOutputStream::WriteStringToArray(data, target);
 
       // End group.
-      target =
-        io::CodedOutputStream::WriteTagToArray(kMessageSetItemEndTag, target);
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetItemEndTag, target);
     }
   }
 
@@ -321,32 +304,38 @@
     switch (field.type()) {
       case UnknownField::TYPE_VARINT:
         size += io::CodedOutputStream::VarintSize32(
-          MakeTag(field.number(), WIRETYPE_VARINT));
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_VARINT));
         size += io::CodedOutputStream::VarintSize64(field.varint());
         break;
       case UnknownField::TYPE_FIXED32:
         size += io::CodedOutputStream::VarintSize32(
-          MakeTag(field.number(), WIRETYPE_FIXED32));
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED32));
         size += sizeof(int32);
         break;
       case UnknownField::TYPE_FIXED64:
         size += io::CodedOutputStream::VarintSize32(
-          MakeTag(field.number(), WIRETYPE_FIXED64));
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED64));
         size += sizeof(int64);
         break;
       case UnknownField::TYPE_LENGTH_DELIMITED:
         size += io::CodedOutputStream::VarintSize32(
-          MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED));
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
         size += io::CodedOutputStream::VarintSize32(
-          field.length_delimited().size());
+            field.length_delimited().size());
         size += field.length_delimited().size();
         break;
       case UnknownField::TYPE_GROUP:
         size += io::CodedOutputStream::VarintSize32(
-          MakeTag(field.number(), WIRETYPE_START_GROUP));
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_START_GROUP));
         size += ComputeUnknownFieldsSize(field.group());
         size += io::CodedOutputStream::VarintSize32(
-          MakeTag(field.number(), WIRETYPE_END_GROUP));
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_END_GROUP));
         break;
     }
   }
@@ -363,7 +352,7 @@
     // The only unknown fields that are allowed to exist in a MessageSet are
     // messages, which are length-delimited.
     if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
-      size += kMessageSetItemTagsSize;
+      size += WireFormatLite::kMessageSetItemTagsSize;
       size += io::CodedOutputStream::VarintSize32(field.number());
       size += io::CodedOutputStream::VarintSize32(
         field.length_delimited().size());
@@ -388,7 +377,8 @@
       return true;
     }
 
-    if (GetTagWireType(tag) == WIRETYPE_END_GROUP) {
+    if (WireFormatLite::GetTagWireType(tag) ==
+        WireFormatLite::WIRETYPE_END_GROUP) {
       // Must be the end of the message.
       return true;
     }
@@ -396,7 +386,7 @@
     const FieldDescriptor* field = NULL;
 
     if (descriptor != NULL) {
-      int field_number = GetTagFieldNumber(tag);
+      int field_number = WireFormatLite::GetTagFieldNumber(tag);
       field = descriptor->FindFieldByNumber(field_number);
 
       // If that failed, check if the field is an extension.
@@ -408,7 +398,7 @@
       // MessageSet item, then parse that.
       if (field == NULL &&
           descriptor->options().message_set_wire_format() &&
-          tag == kMessageSetItemStartTag) {
+          tag == WireFormatLite::kMessageSetItemStartTag) {
         if (!ParseAndMergeMessageSetItem(input, message)) {
           return false;
         }
@@ -430,7 +420,7 @@
   const Reflection* message_reflection = message->GetReflection();
 
   if (field == NULL ||
-      GetTagWireType(tag) != WireTypeForField(field)) {
+      WireFormatLite::GetTagWireType(tag) != WireTypeForField(field)) {
     // We don't recognize this field.  Either the field number is unknown
     // or the wire type doesn't match.  Put it in our unknown field set.
     return SkipField(input, tag,
@@ -443,14 +433,14 @@
     io::CodedInputStream::Limit limit = input->PushLimit(length);
 
     switch (field->type()) {
-#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD)    \
-      case FieldDescriptor::TYPE_##TYPE: {                                \
-        while (input->BytesUntilLimit() > 0) {                            \
-          CPPTYPE value;                                                  \
-          if (!Read##TYPE_METHOD(input, &value)) return false;            \
-          message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
-        }                                                                 \
-        break;                                                            \
+#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD)         \
+      case FieldDescriptor::TYPE_##TYPE: {                                     \
+        while (input->BytesUntilLimit() > 0) {                                 \
+          CPPTYPE value;                                                       \
+          if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \
+          message_reflection->Add##CPPTYPE_METHOD(message, field, value);      \
+        }                                                                      \
+        break;                                                                 \
       }
 
       HANDLE_PACKED_TYPE( INT32,  Int32,  int32,  Int32)
@@ -474,7 +464,7 @@
       case FieldDescriptor::TYPE_ENUM: {
         while (input->BytesUntilLimit() > 0) {
           int value;
-          if (!ReadEnum(input, &value)) return false;
+          if (!WireFormatLite::ReadEnum(input, &value)) return false;
           const EnumValueDescriptor* enum_value =
               field->enum_type()->FindValueByNumber(value);
           if (enum_value != NULL) {
@@ -498,16 +488,16 @@
     input->PopLimit(limit);
   } else {
     switch (field->type()) {
-#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD)           \
-      case FieldDescriptor::TYPE_##TYPE: {                                \
-        CPPTYPE value;                                                    \
-        if (!Read##TYPE_METHOD(input, &value)) return false;              \
-        if (field->is_repeated()) {                                       \
-          message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
-        } else {                                                          \
-          message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
-        }                                                                 \
-        break;                                                            \
+#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD)               \
+      case FieldDescriptor::TYPE_##TYPE: {                                    \
+        CPPTYPE value;                                                        \
+        if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false;  \
+        if (field->is_repeated()) {                                           \
+          message_reflection->Add##CPPTYPE_METHOD(message, field, value);     \
+        } else {                                                              \
+          message_reflection->Set##CPPTYPE_METHOD(message, field, value);     \
+        }                                                                     \
+        break;                                                                \
       }
 
       HANDLE_TYPE( INT32,  Int32,  int32,  Int32)
@@ -534,7 +524,7 @@
 
       case FieldDescriptor::TYPE_ENUM: {
         int value;
-        if (!ReadEnum(input, &value)) return false;
+        if (!WireFormatLite::ReadEnum(input, &value)) return false;
         const EnumValueDescriptor* enum_value =
           field->enum_type()->FindValueByNumber(value);
         if (enum_value != NULL) {
@@ -548,7 +538,7 @@
           // UnknownFieldSet.
           int64 sign_extended_value = static_cast<int64>(value);
           message_reflection->MutableUnknownFields(message)
-                            ->AddVarint(GetTagFieldNumber(tag),
+                            ->AddVarint(WireFormatLite::GetTagFieldNumber(tag),
                                         sign_extended_value);
         }
         break;
@@ -563,7 +553,8 @@
           sub_message = message_reflection->MutableMessage(message, field);
         }
 
-        if (!ReadGroup(GetTagFieldNumber(tag), input, sub_message))
+        if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
+                                       input, sub_message))
           return false;
         break;
       }
@@ -576,7 +567,7 @@
           sub_message = message_reflection->MutableMessage(message, field);
         }
 
-        if (!ReadMessage(input, sub_message)) return false;
+        if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
         break;
       }
     }
@@ -615,10 +606,11 @@
     if (tag == 0) return false;
 
     switch (tag) {
-      case kMessageSetTypeIdTag: {
+      case WireFormatLite::kMessageSetTypeIdTag: {
         uint32 type_id;
         if (!input->ReadVarint32(&type_id)) return false;
-        fake_tag = MakeTag(type_id, WIRETYPE_LENGTH_DELIMITED);
+        fake_tag = WireFormatLite::MakeTag(
+            type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
         field = message_reflection->FindKnownExtensionByNumber(type_id);
 
         if (!message_data.empty()) {
@@ -637,7 +629,7 @@
         break;
       }
 
-      case kMessageSetMessageTag: {
+      case WireFormatLite::kMessageSetMessageTag: {
         if (fake_tag == 0) {
           // We haven't seen a type_id yet.  Append this data to message_data.
           string temp;
@@ -655,7 +647,7 @@
         break;
       }
 
-      case kMessageSetItemEndTag: {
+      case WireFormatLite::kMessageSetItemEndTag: {
         return true;
       }
 
@@ -719,7 +711,8 @@
 
   const bool is_packed = field->options().packed();
   if (is_packed && count > 0) {
-    WriteTag(field->number(), WIRETYPE_LENGTH_DELIMITED, output);
+    WireFormatLite::WriteTag(field->number(),
+        WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
     const int data_size = FieldDataOnlyByteSize(field, message);
     output->WriteVarint32(data_size);
   }
@@ -734,9 +727,9 @@
                               message_reflection->Get##CPPTYPE_METHOD(         \
                                 message, field);                               \
         if (is_packed) {                                                       \
-          Write##TYPE_METHOD##NoTag(value, output);                            \
+          WireFormatLite::Write##TYPE_METHOD##NoTag(value, output);            \
         } else {                                                               \
-          Write##TYPE_METHOD(field->number(), value, output);                  \
+          WireFormatLite::Write##TYPE_METHOD(field->number(), value, output);  \
         }                                                                      \
         break;                                                                 \
       }
@@ -761,7 +754,7 @@
 
 #define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD)                       \
       case FieldDescriptor::TYPE_##TYPE:                                     \
-        Write##TYPE_METHOD(                                                  \
+        WireFormatLite::Write##TYPE_METHOD(                                  \
               field->number(),                                               \
               field->is_repeated() ?                                         \
                 message_reflection->GetRepeated##CPPTYPE_METHOD(             \
@@ -779,9 +772,9 @@
           message_reflection->GetRepeatedEnum(message, field, j) :
           message_reflection->GetEnum(message, field);
         if (is_packed) {
-          WriteEnumNoTag(value->number(), output);
+          WireFormatLite::WriteEnumNoTag(value->number(), output);
         } else {
-          WriteEnum(field->number(), value->number(), output);
+          WireFormatLite::WriteEnum(field->number(), value->number(), output);
         }
         break;
       }
@@ -794,7 +787,8 @@
             message_reflection->GetRepeatedStringReference(
               message, field, j, &scratch) :
             message_reflection->GetStringReference(message, field, &scratch);
-          WriteString(field->number(), value, output);
+          VerifyUTF8String(value.data(), value.length(), SERIALIZE);
+          WireFormatLite::WriteString(field->number(), value, output);
         break;
       }
 
@@ -804,7 +798,7 @@
             message_reflection->GetRepeatedStringReference(
               message, field, j, &scratch) :
             message_reflection->GetStringReference(message, field, &scratch);
-          WriteBytes(field->number(), value, output);
+          WireFormatLite::WriteBytes(field->number(), value, output);
         break;
       }
     }
@@ -818,21 +812,21 @@
   const Reflection* message_reflection = message.GetReflection();
 
   // Start group.
-  output->WriteVarint32(kMessageSetItemStartTag);
+  output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
 
   // Write type ID.
-  output->WriteVarint32(kMessageSetTypeIdTag);
+  output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
   output->WriteVarint32(field->number());
 
   // Write message.
-  output->WriteVarint32(kMessageSetMessageTag);
+  output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
 
   const Message& sub_message = message_reflection->GetMessage(message, field);
   output->WriteVarint32(sub_message.GetCachedSize());
   sub_message.SerializeWithCachedSizes(output);
 
   // End group.
-  output->WriteVarint32(kMessageSetItemEndTag);
+  output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
 }
 
 // ===================================================================
@@ -913,19 +907,19 @@
     case FieldDescriptor::TYPE_##TYPE:                                     \
       if (field->is_repeated()) {                                          \
         for (int j = 0; j < count; j++) {                                  \
-          data_size += TYPE_METHOD##Size(                                  \
+          data_size += WireFormatLite::TYPE_METHOD##Size(                  \
             message_reflection->GetRepeated##CPPTYPE_METHOD(               \
               message, field, j));                                         \
         }                                                                  \
       } else {                                                             \
-        data_size += TYPE_METHOD##Size(                                    \
+        data_size += WireFormatLite::TYPE_METHOD##Size(                    \
           message_reflection->Get##CPPTYPE_METHOD(message, field));        \
       }                                                                    \
       break;
 
 #define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD)                               \
     case FieldDescriptor::TYPE_##TYPE:                                     \
-      data_size += count * k##TYPE_METHOD##Size;                           \
+      data_size += count * WireFormatLite::k##TYPE_METHOD##Size;           \
       break;
 
     HANDLE_TYPE( INT32,  Int32,  Int32)
@@ -953,11 +947,11 @@
     case FieldDescriptor::TYPE_ENUM: {
       if (field->is_repeated()) {
         for (int j = 0; j < count; j++) {
-          data_size += EnumSize(
+          data_size += WireFormatLite::EnumSize(
             message_reflection->GetRepeatedEnum(message, field, j)->number());
         }
       } else {
-        data_size += EnumSize(
+        data_size += WireFormatLite::EnumSize(
           message_reflection->GetEnum(message, field)->number());
       }
       break;
@@ -973,7 +967,7 @@
             message_reflection->GetRepeatedStringReference(
               message, field, j, &scratch) :
             message_reflection->GetStringReference(message, field, &scratch);
-          data_size += StringSize(value);
+          data_size += WireFormatLite::StringSize(value);
         }
       break;
     }
@@ -986,7 +980,7 @@
     const Message& message) {
   const Reflection* message_reflection = message.GetReflection();
 
-  int our_size = kMessageSetItemTagsSize;
+  int our_size = WireFormatLite::kMessageSetItemTagsSize;
 
   // type_id
   our_size += io::CodedOutputStream::VarintSize32(field->number());
@@ -1001,6 +995,28 @@
   return our_size;
 }
 
+void WireFormat::VerifyUTF8StringFallback(const char* data,
+                                          int size,
+                                          Operation op) {
+  if (!IsStructurallyValidUTF8(data, size)) {
+    const char* operation_str = NULL;
+    switch (op) {
+      case PARSE:
+        operation_str = "parsing";
+        break;
+      case SERIALIZE:
+        operation_str = "serializing";
+        break;
+      // no default case: have the compiler warn if a case is not covered.
+    }
+    GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
+               << operation_str
+               << " protocol buffer. Strings must contain only UTF-8; "
+                  "use the 'bytes' type for raw bytes.";
+  }
+}
+
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 963f427..c753925 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -40,17 +40,23 @@
 #define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
 
 #include <string>
-#include <google/protobuf/message.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/wire_format_lite.h>
+
+// Do UTF-8 validation on string type in Debug build only
+#ifndef NDEBUG
+#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+#endif
 
 namespace google {
-
 namespace protobuf {
   namespace io {
     class CodedInputStream;      // coded_stream.h
     class CodedOutputStream;     // coded_stream.h
   }
-  class UnknownFieldSet;       // unknown_field_set.h
+  class UnknownFieldSet;         // unknown_field_set.h
 }
 
 namespace protobuf {
@@ -60,13 +66,26 @@
 // protocol-complier-generated message classes.  It must not be called
 // directly by clients.
 //
-// This class contains helpers for implementing the binary protocol buffer
-// wire format.  These helpers are called primarily by generated code.  The
-// class also contains reflection-based implementations of the wire format.
+// This class contains code for implementing the binary protocol buffer
+// wire format via reflection.  The WireFormatLite class implements the
+// non-reflection based routines.
 //
-// This class is really a namespace that contains only static methods.
+// This class is really a namespace that contains only static methods
 class LIBPROTOBUF_EXPORT WireFormat {
  public:
+
+  // Given a field return its WireType
+  static inline WireFormatLite::WireType WireTypeForField(
+      const FieldDescriptor* field);
+
+  // Given a FieldSescriptor::Type return its WireType
+  static inline WireFormatLite::WireType WireTypeForFieldType(
+      FieldDescriptor::Type type);
+
+  // Compute the byte size of a tag.  For groups, this includes both the start
+  // and end tags.
+  static inline int TagSize(int field_number, FieldDescriptor::Type type);
+
   // These procedures can be used to implement the methods of Message which
   // handle parsing and serialization of the protocol buffer wire format
   // using only the Reflection interface.  When you ask the protocol
@@ -152,41 +171,6 @@
   static int ComputeUnknownMessageSetItemsSize(
       const UnknownFieldSet& unknown_fields);
 
-  // -----------------------------------------------------------------
-  // Helper constants and functions related to the format.  These are
-  // mostly meant for internal and generated code to use.
-
-  // The wire format is composed of a sequence of tag/value pairs, each
-  // of which contains the value of one field (or one element of a repeated
-  // field).  Each tag is encoded as a varint.  The lower bits of the tag
-  // identify its wire type, which specifies the format of the data to follow.
-  // The rest of the bits contain the field number.  Each type of field (as
-  // declared by FieldDescriptor::Type, in descriptor.h) maps to one of
-  // these wire types.  Immediately following each tag is the field's value,
-  // encoded in the format specified by the wire type.  Because the tag
-  // identifies the encoding of this data, it is possible to skip
-  // unrecognized fields for forwards compatibility.
-
-  enum WireType {
-    WIRETYPE_VARINT           = 0,
-    WIRETYPE_FIXED64          = 1,
-    WIRETYPE_LENGTH_DELIMITED = 2,
-    WIRETYPE_START_GROUP      = 3,
-    WIRETYPE_END_GROUP        = 4,
-    WIRETYPE_FIXED32          = 5,
-  };
-
-  static inline WireType WireTypeForFieldType(FieldDescriptor::Type type) {
-    return kWireTypeForFieldType[type];
-  }
-  // This is different from WireTypeForFieldType(field->type()) in the case of
-  // packed repeated fields.
-  static inline WireType WireTypeForField(const FieldDescriptor* field);
-
-  // Number of bits in a tag which identify the wire type.
-  static const int kTagTypeBits = 3;
-  // Mask for those bits.
-  static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
 
   // Helper functions for encoding and decoding tags.  (Inlined below and in
   // _inl.h)
@@ -194,28 +178,6 @@
   // This is different from MakeTag(field->number(), field->type()) in the case
   // of packed repeated fields.
   static uint32 MakeTag(const FieldDescriptor* field);
-  static uint32 MakeTag(int field_number, WireType type);
-  static WireType GetTagWireType(uint32 tag);
-  static int GetTagFieldNumber(uint32 tag);
-
-  // Helper functions for converting between floats/doubles and IEEE-754
-  // uint32s/uint64s so that they can be written.  (Assumes your platform
-  // uses IEEE-754 floats.)
-  static uint32 EncodeFloat(float value);
-  static float DecodeFloat(uint32 value);
-  static uint64 EncodeDouble(double value);
-  static double DecodeDouble(uint64 value);
-
-  // Helper functions for mapping signed integers to unsigned integers in
-  // such a way that numbers with small magnitudes will encode to smaller
-  // varints.  If you simply static_cast a negative number to an unsigned
-  // number and varint-encode it, it will always take 10 bytes, defeating
-  // the purpose of varint.  So, for the "sint32" and "sint64" field types,
-  // we ZigZag-encode the values.
-  static uint32 ZigZagEncode32(int32 n);
-  static int32  ZigZagDecode32(uint32 n);
-  static uint64 ZigZagEncode64(int64 n);
-  static int64  ZigZagDecode64(uint64 n);
 
   // Parse a single field.  The input should start out positioned immidately
   // after the tag.
@@ -238,223 +200,6 @@
       const FieldDescriptor* field,        // Cannot be NULL
       const Message& message);
 
-  // =================================================================
-  // Methods for reading/writing individual field.  The implementations
-  // of these methods are defined in wire_format_inl.h; you must #include
-  // that file to use these.
-
-// Avoid ugly line wrapping
-#define input  io::CodedInputStream*  input
-#define output io::CodedOutputStream* output
-#define field_number int field_number
-#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-
-  // Read fields, not including tags.  The assumption is that you already
-  // read the tag to determine what field to read.
-  static inline bool ReadInt32   (input,  int32* value);
-  static inline bool ReadInt64   (input,  int64* value);
-  static inline bool ReadUInt32  (input, uint32* value);
-  static inline bool ReadUInt64  (input, uint64* value);
-  static inline bool ReadSInt32  (input,  int32* value);
-  static inline bool ReadSInt64  (input,  int64* value);
-  static inline bool ReadFixed32 (input, uint32* value);
-  static inline bool ReadFixed64 (input, uint64* value);
-  static inline bool ReadSFixed32(input,  int32* value);
-  static inline bool ReadSFixed64(input,  int64* value);
-  static inline bool ReadFloat   (input,  float* value);
-  static inline bool ReadDouble  (input, double* value);
-  static inline bool ReadBool    (input,   bool* value);
-  static inline bool ReadEnum    (input,    int* value);
-
-  static inline bool ReadString(input, string* value);
-  static inline bool ReadBytes (input, string* value);
-
-  static inline bool ReadGroup  (field_number, input, Message* value);
-  static inline bool ReadMessage(input, Message* value);
-
-  // Like above, but de-virtualize the call to MergePartialFromCodedStream().
-  // The pointer must point at an instance of MessageType, *not* a subclass (or
-  // the subclass must not override MergePartialFromCodedStream()).
-  template<typename MessageType>
-  static inline bool ReadGroupNoVirtual(field_number, input,
-                                        MessageType* value);
-  template<typename MessageType>
-  static inline bool ReadMessageNoVirtual(input, MessageType* value);
-
-  // Write a tag.  The Write*() functions typically include the tag, so
-  // normally there's no need to call this unless using the Write*NoTag()
-  // variants.
-  static inline void WriteTag(field_number, WireType type, output) INL;
-
-  // Write fields, without tags.
-  static inline void WriteInt32NoTag   (int32 value, output) INL;
-  static inline void WriteInt64NoTag   (int64 value, output) INL;
-  static inline void WriteUInt32NoTag  (uint32 value, output) INL;
-  static inline void WriteUInt64NoTag  (uint64 value, output) INL;
-  static inline void WriteSInt32NoTag  (int32 value, output) INL;
-  static inline void WriteSInt64NoTag  (int64 value, output) INL;
-  static inline void WriteFixed32NoTag (uint32 value, output) INL;
-  static inline void WriteFixed64NoTag (uint64 value, output) INL;
-  static inline void WriteSFixed32NoTag(int32 value, output) INL;
-  static inline void WriteSFixed64NoTag(int64 value, output) INL;
-  static inline void WriteFloatNoTag   (float value, output) INL;
-  static inline void WriteDoubleNoTag  (double value, output) INL;
-  static inline void WriteBoolNoTag    (bool value, output) INL;
-  static inline void WriteEnumNoTag    (int value, output) INL;
-
-  // Write fields, including tags.
-  static inline void WriteInt32   (field_number,  int32 value, output) INL;
-  static inline void WriteInt64   (field_number,  int64 value, output) INL;
-  static inline void WriteUInt32  (field_number, uint32 value, output) INL;
-  static inline void WriteUInt64  (field_number, uint64 value, output) INL;
-  static inline void WriteSInt32  (field_number,  int32 value, output) INL;
-  static inline void WriteSInt64  (field_number,  int64 value, output) INL;
-  static inline void WriteFixed32 (field_number, uint32 value, output) INL;
-  static inline void WriteFixed64 (field_number, uint64 value, output) INL;
-  static inline void WriteSFixed32(field_number,  int32 value, output) INL;
-  static inline void WriteSFixed64(field_number,  int64 value, output) INL;
-  static inline void WriteFloat   (field_number,  float value, output) INL;
-  static inline void WriteDouble  (field_number, double value, output) INL;
-  static inline void WriteBool    (field_number,   bool value, output) INL;
-  static inline void WriteEnum    (field_number,    int value, output) INL;
-
-  static inline void WriteString(field_number, const string& value, output) INL;
-  static inline void WriteBytes (field_number, const string& value, output) INL;
-
-  static inline void WriteGroup(field_number, const Message& value, output) INL;
-  static inline void WriteMessage(
-    field_number, const Message& value, output) INL;
-
-  // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
-  // pointer must point at an instance of MessageType, *not* a subclass (or
-  // the subclass must not override SerializeWithCachedSizes()).
-  template<typename MessageType>
-  static inline void WriteGroupNoVirtual(
-    field_number, const MessageType& value, output) INL;
-  template<typename MessageType>
-  static inline void WriteMessageNoVirtual(
-    field_number, const MessageType& value, output) INL;
-
-#undef output
-#define output uint8* target
-
-  // Like above, but use only *ToArray methods of CodedOutputStream.
-  static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
-
-  // Write fields, without tags.
-  static inline uint8* WriteInt32NoTagToArray   (int32 value, output) INL;
-  static inline uint8* WriteInt64NoTagToArray   (int64 value, output) INL;
-  static inline uint8* WriteUInt32NoTagToArray  (uint32 value, output) INL;
-  static inline uint8* WriteUInt64NoTagToArray  (uint64 value, output) INL;
-  static inline uint8* WriteSInt32NoTagToArray  (int32 value, output) INL;
-  static inline uint8* WriteSInt64NoTagToArray  (int64 value, output) INL;
-  static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
-  static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
-  static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
-  static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
-  static inline uint8* WriteFloatNoTagToArray   (float value, output) INL;
-  static inline uint8* WriteDoubleNoTagToArray  (double value, output) INL;
-  static inline uint8* WriteBoolNoTagToArray    (bool value, output) INL;
-  static inline uint8* WriteEnumNoTagToArray    (int value, output) INL;
-
-  // Write fields, including tags.
-  static inline uint8* WriteInt32ToArray(
-    field_number, int32 value, output) INL;
-  static inline uint8* WriteInt64ToArray(
-    field_number, int64 value, output) INL;
-  static inline uint8* WriteUInt32ToArray(
-    field_number, uint32 value, output) INL;
-  static inline uint8* WriteUInt64ToArray(
-    field_number, uint64 value, output) INL;
-  static inline uint8* WriteSInt32ToArray(
-    field_number, int32 value, output) INL;
-  static inline uint8* WriteSInt64ToArray(
-    field_number, int64 value, output) INL;
-  static inline uint8* WriteFixed32ToArray(
-    field_number, uint32 value, output) INL;
-  static inline uint8* WriteFixed64ToArray(
-    field_number, uint64 value, output) INL;
-  static inline uint8* WriteSFixed32ToArray(
-    field_number, int32 value, output) INL;
-  static inline uint8* WriteSFixed64ToArray(
-    field_number, int64 value, output) INL;
-  static inline uint8* WriteFloatToArray(
-    field_number, float value, output) INL;
-  static inline uint8* WriteDoubleToArray(
-    field_number, double value, output) INL;
-  static inline uint8* WriteBoolToArray(
-    field_number, bool value, output) INL;
-  static inline uint8* WriteEnumToArray(
-    field_number, int value, output) INL;
-
-  static inline uint8* WriteStringToArray(
-    field_number, const string& value, output) INL;
-  static inline uint8* WriteBytesToArray(
-    field_number, const string& value, output) INL;
-
-  static inline uint8* WriteGroupToArray(
-      field_number, const Message& value, output) INL;
-  static inline uint8* WriteMessageToArray(
-      field_number, const Message& value, output) INL;
-
-  // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
-  // pointer must point at an instance of MessageType, *not* a subclass (or
-  // the subclass must not override SerializeWithCachedSizes()).
-  template<typename MessageType>
-  static inline uint8* WriteGroupNoVirtualToArray(
-    field_number, const MessageType& value, output) INL;
-  template<typename MessageType>
-  static inline uint8* WriteMessageNoVirtualToArray(
-    field_number, const MessageType& value, output) INL;
-
-#undef output
-#undef input
-#undef INL
-
-  // Compute the byte size of a tag.  For groups, this includes both the start
-  // and end tags.
-  static inline int TagSize(field_number, FieldDescriptor::Type type);
-
-#undef field_number
-
-  // Compute the byte size of a field.  The XxSize() functions do NOT include
-  // the tag, so you must also call TagSize().  (This is because, for repeated
-  // fields, you should only call TagSize() once and multiply it by the element
-  // count, but you may have to call XxSize() for each individual element.)
-  static inline int Int32Size   ( int32 value);
-  static inline int Int64Size   ( int64 value);
-  static inline int UInt32Size  (uint32 value);
-  static inline int UInt64Size  (uint64 value);
-  static inline int SInt32Size  ( int32 value);
-  static inline int SInt64Size  ( int64 value);
-  static inline int EnumSize    (   int value);
-
-  // These types always have the same size.
-  static const int kFixed32Size  = 4;
-  static const int kFixed64Size  = 8;
-  static const int kSFixed32Size = 4;
-  static const int kSFixed64Size = 8;
-  static const int kFloatSize    = 4;
-  static const int kDoubleSize   = 8;
-  static const int kBoolSize     = 1;
-
-  static inline int StringSize(const string& value);
-  static inline int BytesSize (const string& value);
-
-  static inline int GroupSize  (const Message& value);
-  static inline int MessageSize(const Message& value);
-
-  // Like above, but de-virtualize the call to ByteSize().  The
-  // pointer must point at an instance of MessageType, *not* a subclass (or
-  // the subclass must not override ByteSize()).
-  template<typename MessageType>
-  static inline int GroupSizeNoVirtual  (const MessageType& value);
-  template<typename MessageType>
-  static inline int MessageSizeNoVirtual(const MessageType& value);
-
- private:
-  static const WireType kWireTypeForFieldType[];
-
   // Parse/serialize a MessageSet::Item group.  Used with messages that use
   // opion message_set_wire_format = true.
   static bool ParseAndMergeMessageSetItem(
@@ -476,96 +221,81 @@
       const FieldDescriptor* field,        // Cannot be NULL
       const Message& message);
 
+  enum Operation {
+    PARSE,
+    SERIALIZE,
+  };
+
+  // Verifies that a string field is valid UTF8, logging an error if not.
+  static void VerifyUTF8String(const char* data, int size, Operation op);
+
+ private:
+  // Verifies that a string field is valid UTF8, logging an error if not.
+  static void VerifyUTF8StringFallback(
+      const char* data,
+      int size,
+      Operation op);
+
+
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
 };
 
+// Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet.
+class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
+ public:
+  UnknownFieldSetFieldSkipper(UnknownFieldSet* unknown_fields)
+      : unknown_fields_(unknown_fields) {}
+  virtual ~UnknownFieldSetFieldSkipper() {}
+
+  // implements FieldSkipper -----------------------------------------
+  virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
+  virtual bool SkipMessage(io::CodedInputStream* input);
+  virtual void SkipUnknownEnum(int field_number, int value);
+
+ private:
+  UnknownFieldSet* unknown_fields_;
+};
+
 // inline methods ====================================================
 
-// This macro does the same thing as WireFormat::MakeTag(), but the
-// result is usable as a compile-time constant, which makes it usable
-// as a switch case or a template input.  WireFormat::MakeTag() is more
-// type-safe, though, so prefer it if possible.
-#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE)             \
-  static_cast<uint32>(                                              \
-    ((FIELD_NUMBER) << ::google::protobuf::internal::WireFormat::kTagTypeBits) | (TYPE))
-
-inline uint32 WireFormat::MakeTag(int field_number, WireType type) {
-  return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
+inline WireFormatLite::WireType WireFormat::WireTypeForField(
+    const FieldDescriptor* field) {
+  if (field->options().packed()) {
+    return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+  } else {
+    return WireTypeForFieldType(field->type());
+  }
 }
 
-inline WireFormat::WireType WireFormat::GetTagWireType(uint32 tag) {
-  return static_cast<WireType>(tag & kTagTypeMask);
+inline WireFormatLite::WireType WireFormat::WireTypeForFieldType(
+    FieldDescriptor::Type type) {
+  // Some compilers don't like enum -> enum casts, so we implicit_cast to
+  // int first.
+  return WireFormatLite::WireTypeForFieldType(
+      static_cast<WireFormatLite::FieldType>(
+        implicit_cast<int>(type)));
 }
 
-inline int WireFormat::GetTagFieldNumber(uint32 tag) {
-  return static_cast<int>(tag >> kTagTypeBits);
+inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) {
+  return WireFormatLite::MakeTag(field->number(), WireTypeForField(field));
 }
 
-inline uint32 WireFormat::EncodeFloat(float value) {
-  union {float f; uint32 i;};
-  f = value;
-  return i;
+inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) {
+  // Some compilers don't like enum -> enum casts, so we implicit_cast to
+  // int first.
+  return WireFormatLite::TagSize(field_number,
+      static_cast<WireFormatLite::FieldType>(
+        implicit_cast<int>(type)));
 }
 
-inline float WireFormat::DecodeFloat(uint32 value) {
-  union {float f; uint32 i;};
-  i = value;
-  return f;
+inline void WireFormat::VerifyUTF8String(const char* data, int size,
+    WireFormat::Operation op) {
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  WireFormat::VerifyUTF8StringFallback(data, size, op);
+#endif
 }
 
-inline uint64 WireFormat::EncodeDouble(double value) {
-  union {double f; uint64 i;};
-  f = value;
-  return i;
-}
-
-inline double WireFormat::DecodeDouble(uint64 value) {
-  union {double f; uint64 i;};
-  i = value;
-  return f;
-}
-
-// ZigZag Transform:  Encodes signed integers so that they can be
-// effectively used with varint encoding.
-//
-// varint operates on unsigned integers, encoding smaller numbers into
-// fewer bytes.  If you try to use it on a signed integer, it will treat
-// this number as a very large unsigned integer, which means that even
-// small signed numbers like -1 will take the maximum number of bytes
-// (10) to encode.  ZigZagEncode() maps signed integers to unsigned
-// in such a way that those with a small absolute value will have smaller
-// encoded values, making them appropriate for encoding using varint.
-//
-//       int32 ->     uint32
-// -------------------------
-//           0 ->          0
-//          -1 ->          1
-//           1 ->          2
-//          -2 ->          3
-//         ... ->        ...
-//  2147483647 -> 4294967294
-// -2147483648 -> 4294967295
-//
-//        >> encode >>
-//        << decode <<
-
-inline uint32 WireFormat::ZigZagEncode32(int32 n) {
-  // Note:  the right-shift must be arithmetic
-  return (n << 1) ^ (n >> 31);
-}
-
-inline int32 WireFormat::ZigZagDecode32(uint32 n) {
-  return (n >> 1) ^ -static_cast<int32>(n & 1);
-}
-
-inline uint64 WireFormat::ZigZagEncode64(int64 n) {
-  // Note:  the right-shift must be arithmetic
-  return (n << 1) ^ (n >> 63);
-}
-
-inline int64 WireFormat::ZigZagDecode64(uint64 n) {
-  return (n >> 1) ^ -static_cast<int64>(n & 1);
-}
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/wire_format_inl.h b/src/google/protobuf/wire_format_inl.h
deleted file mode 100644
index 6925608..0000000
--- a/src/google/protobuf/wire_format_inl.h
+++ /dev/null
@@ -1,687 +0,0 @@
-// 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.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_INL_H__
-#define GOOGLE_PROTOBUF_WIRE_FORMAT_INL_H__
-
-#include <string>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-
-
-// Do UTF-8 validation on string type in Debug build only
-#ifndef NDEBUG
-#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-#endif
-
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-inline WireFormat::WireType WireFormat::WireTypeForField(
-    const FieldDescriptor* field) {
-  if (field->options().packed()) {
-    return WIRETYPE_LENGTH_DELIMITED;
-  } else {
-    return WireTypeForFieldType(field->type());
-  }
-}
-
-inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) {
-  return MakeTag(field->number(), WireTypeForField(field));
-}
-
-inline bool WireFormat::ReadInt32(io::CodedInputStream* input, int32* value) {
-  uint32 temp;
-  if (!input->ReadVarint32(&temp)) return false;
-  *value = static_cast<int32>(temp);
-  return true;
-}
-inline bool WireFormat::ReadInt64(io::CodedInputStream* input, int64* value) {
-  uint64 temp;
-  if (!input->ReadVarint64(&temp)) return false;
-  *value = static_cast<int64>(temp);
-  return true;
-}
-inline bool WireFormat::ReadUInt32(io::CodedInputStream* input, uint32* value) {
-  return input->ReadVarint32(value);
-}
-inline bool WireFormat::ReadUInt64(io::CodedInputStream* input, uint64* value) {
-  return input->ReadVarint64(value);
-}
-inline bool WireFormat::ReadSInt32(io::CodedInputStream* input, int32* value) {
-  uint32 temp;
-  if (!input->ReadVarint32(&temp)) return false;
-  *value = ZigZagDecode32(temp);
-  return true;
-}
-inline bool WireFormat::ReadSInt64(io::CodedInputStream* input, int64* value) {
-  uint64 temp;
-  if (!input->ReadVarint64(&temp)) return false;
-  *value = ZigZagDecode64(temp);
-  return true;
-}
-inline bool WireFormat::ReadFixed32(io::CodedInputStream* input,
-                                    uint32* value) {
-  return input->ReadLittleEndian32(value);
-}
-inline bool WireFormat::ReadFixed64(io::CodedInputStream* input,
-                                    uint64* value) {
-  return input->ReadLittleEndian64(value);
-}
-inline bool WireFormat::ReadSFixed32(io::CodedInputStream* input,
-                                     int32* value) {
-  uint32 temp;
-  if (!input->ReadLittleEndian32(&temp)) return false;
-  *value = static_cast<int32>(temp);
-  return true;
-}
-inline bool WireFormat::ReadSFixed64(io::CodedInputStream* input,
-                                     int64* value) {
-  uint64 temp;
-  if (!input->ReadLittleEndian64(&temp)) return false;
-  *value = static_cast<int64>(temp);
-  return true;
-}
-inline bool WireFormat::ReadFloat(io::CodedInputStream* input, float* value) {
-  uint32 temp;
-  if (!input->ReadLittleEndian32(&temp)) return false;
-  *value = DecodeFloat(temp);
-  return true;
-}
-inline bool WireFormat::ReadDouble(io::CodedInputStream* input, double* value) {
-  uint64 temp;
-  if (!input->ReadLittleEndian64(&temp)) return false;
-  *value = DecodeDouble(temp);
-  return true;
-}
-inline bool WireFormat::ReadBool(io::CodedInputStream* input, bool* value) {
-  uint32 temp;
-  if (!input->ReadVarint32(&temp)) return false;
-  *value = temp != 0;
-  return true;
-}
-inline bool WireFormat::ReadEnum(io::CodedInputStream* input, int* value) {
-  uint32 temp;
-  if (!input->ReadVarint32(&temp)) return false;
-  *value = static_cast<int>(temp);
-  return true;
-}
-
-inline bool WireFormat::ReadString(io::CodedInputStream* input, string* value) {
-  // String is for UTF-8 text only
-  uint32 length;
-  if (!input->ReadVarint32(&length)) return false;
-  if (!input->ReadString(value, length)) return false;
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  if (!IsStructurallyValidUTF8(value->data(), length)) {
-    GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
-               "parsing protocol buffer. Strings must contain only UTF-8; "
-               "use the 'bytes' type for raw bytes.";
-  }
-#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  return true;
-}
-inline bool WireFormat::ReadBytes(io::CodedInputStream* input, string* value) {
-  uint32 length;
-  if (!input->ReadVarint32(&length)) return false;
-  return input->ReadString(value, length);
-}
-
-
-inline bool WireFormat::ReadGroup(int field_number,
-                                  io::CodedInputStream* input,
-                                  Message* value) {
-  if (!input->IncrementRecursionDepth()) return false;
-  if (!value->MergePartialFromCodedStream(input)) return false;
-  input->DecrementRecursionDepth();
-  // Make sure the last thing read was an end tag for this group.
-  if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
-    return false;
-  }
-  return true;
-}
-inline bool WireFormat::ReadMessage(io::CodedInputStream* input,
-                                    Message* value) {
-  uint32 length;
-  if (!input->ReadVarint32(&length)) return false;
-  if (!input->IncrementRecursionDepth()) return false;
-  io::CodedInputStream::Limit limit = input->PushLimit(length);
-  if (!value->MergePartialFromCodedStream(input)) return false;
-  // Make sure that parsing stopped when the limit was hit, not at an endgroup
-  // tag.
-  if (!input->ConsumedEntireMessage()) return false;
-  input->PopLimit(limit);
-  input->DecrementRecursionDepth();
-  return true;
-}
-
-template<typename MessageType>
-inline bool WireFormat::ReadGroupNoVirtual(int field_number,
-                                           io::CodedInputStream* input,
-                                           MessageType* value) {
-  if (!input->IncrementRecursionDepth()) return false;
-  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
-  input->DecrementRecursionDepth();
-  // Make sure the last thing read was an end tag for this group.
-  if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
-    return false;
-  }
-  return true;
-}
-template<typename MessageType>
-inline bool WireFormat::ReadMessageNoVirtual(io::CodedInputStream* input,
-                                             MessageType* value) {
-  uint32 length;
-  if (!input->ReadVarint32(&length)) return false;
-  if (!input->IncrementRecursionDepth()) return false;
-  io::CodedInputStream::Limit limit = input->PushLimit(length);
-  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
-  // Make sure that parsing stopped when the limit was hit, not at an endgroup
-  // tag.
-  if (!input->ConsumedEntireMessage()) return false;
-  input->PopLimit(limit);
-  input->DecrementRecursionDepth();
-  return true;
-}
-
-// ===================================================================
-
-inline void WireFormat::WriteTag(int field_number, WireType type,
-                                 io::CodedOutputStream* output) {
-  output->WriteTag(MakeTag(field_number, type));
-}
-
-inline void WireFormat::WriteInt32NoTag(int32 value,
-                                        io::CodedOutputStream* output) {
-  output->WriteVarint32SignExtended(value);
-}
-inline void WireFormat::WriteInt64NoTag(int64 value,
-                                        io::CodedOutputStream* output) {
-  output->WriteVarint64(static_cast<uint64>(value));
-}
-inline void WireFormat::WriteUInt32NoTag(uint32 value,
-                                         io::CodedOutputStream* output) {
-  output->WriteVarint32(value);
-}
-inline void WireFormat::WriteUInt64NoTag(uint64 value,
-                                         io::CodedOutputStream* output) {
-  output->WriteVarint64(value);
-}
-inline void WireFormat::WriteSInt32NoTag(int32 value,
-                                         io::CodedOutputStream* output) {
-  output->WriteVarint32(ZigZagEncode32(value));
-}
-inline void WireFormat::WriteSInt64NoTag(int64 value,
-                                         io::CodedOutputStream* output) {
-  output->WriteVarint64(ZigZagEncode64(value));
-}
-inline void WireFormat::WriteFixed32NoTag(uint32 value,
-                                          io::CodedOutputStream* output) {
-  output->WriteLittleEndian32(value);
-}
-inline void WireFormat::WriteFixed64NoTag(uint64 value,
-                                          io::CodedOutputStream* output) {
-  output->WriteLittleEndian64(value);
-}
-inline void WireFormat::WriteSFixed32NoTag(int32 value,
-                                           io::CodedOutputStream* output) {
-  output->WriteLittleEndian32(static_cast<uint32>(value));
-}
-inline void WireFormat::WriteSFixed64NoTag(int64 value,
-                                           io::CodedOutputStream* output) {
-  output->WriteLittleEndian64(static_cast<uint64>(value));
-}
-inline void WireFormat::WriteFloatNoTag(float value,
-                                        io::CodedOutputStream* output) {
-  output->WriteLittleEndian32(EncodeFloat(value));
-}
-inline void WireFormat::WriteDoubleNoTag(double value,
-                                         io::CodedOutputStream* output) {
-  output->WriteLittleEndian64(EncodeDouble(value));
-}
-inline void WireFormat::WriteBoolNoTag(bool value,
-                                       io::CodedOutputStream* output) {
-  output->WriteVarint32(value ? 1 : 0);
-}
-inline void WireFormat::WriteEnumNoTag(int value,
-                                       io::CodedOutputStream* output) {
-  output->WriteVarint32SignExtended(value);
-}
-
-inline void WireFormat::WriteInt32(int field_number, int32 value,
-                                   io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteInt32NoTag(value, output);
-}
-inline void WireFormat::WriteInt64(int field_number, int64 value,
-                                   io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteInt64NoTag(value, output);
-}
-inline void WireFormat::WriteUInt32(int field_number, uint32 value,
-                                    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteUInt32NoTag(value, output);
-}
-inline void WireFormat::WriteUInt64(int field_number, uint64 value,
-                                    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteUInt64NoTag(value, output);
-}
-inline void WireFormat::WriteSInt32(int field_number, int32 value,
-                                    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteSInt32NoTag(value, output);
-}
-inline void WireFormat::WriteSInt64(int field_number, int64 value,
-                                    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteSInt64NoTag(value, output);
-}
-inline void WireFormat::WriteFixed32(int field_number, uint32 value,
-                                     io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_FIXED32, output);
-  WriteFixed32NoTag(value, output);
-}
-inline void WireFormat::WriteFixed64(int field_number, uint64 value,
-                                     io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_FIXED64, output);
-  WriteFixed64NoTag(value, output);
-}
-inline void WireFormat::WriteSFixed32(int field_number, int32 value,
-                                      io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_FIXED32, output);
-  WriteSFixed32NoTag(value, output);
-}
-inline void WireFormat::WriteSFixed64(int field_number, int64 value,
-                                      io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_FIXED64, output);
-  WriteSFixed64NoTag(value, output);
-}
-inline void WireFormat::WriteFloat(int field_number, float value,
-                                   io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_FIXED32, output);
-  WriteFloatNoTag(value, output);
-}
-inline void WireFormat::WriteDouble(int field_number, double value,
-                                    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_FIXED64, output);
-  WriteDoubleNoTag(value, output);
-}
-inline void WireFormat::WriteBool(int field_number, bool value,
-                                  io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteBoolNoTag(value, output);
-}
-inline void WireFormat::WriteEnum(int field_number, int value,
-                                  io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_VARINT, output);
-  WriteEnumNoTag(value, output);
-}
-
-inline void WireFormat::WriteString(int field_number, const string& value,
-                                    io::CodedOutputStream* output) {
-  // String is for UTF-8 text only
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  if (!IsStructurallyValidUTF8(value.data(), value.size())) {
-    GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
-               "serializing protocol buffer. Strings must contain only UTF-8; "
-               "use the 'bytes' type for raw bytes.";
-  }
-#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  output->WriteVarint32(value.size());
-  output->WriteString(value);
-}
-inline void WireFormat::WriteBytes(int field_number, const string& value,
-                                   io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  output->WriteVarint32(value.size());
-  output->WriteString(value);
-}
-
-
-inline void WireFormat::WriteGroup(int field_number, const Message& value,
-                                   io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_START_GROUP, output);
-  value.SerializeWithCachedSizes(output);
-  WriteTag(field_number, WIRETYPE_END_GROUP, output);
-}
-inline void WireFormat::WriteMessage(int field_number, const Message& value,
-                                     io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  output->WriteVarint32(value.GetCachedSize());
-  value.SerializeWithCachedSizes(output);
-}
-
-template<typename MessageType>
-inline void WireFormat::WriteGroupNoVirtual(
-    int field_number, const MessageType& value,
-    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_START_GROUP, output);
-  value.MessageType::SerializeWithCachedSizes(output);
-  WriteTag(field_number, WIRETYPE_END_GROUP, output);
-}
-template<typename MessageType>
-inline void WireFormat::WriteMessageNoVirtual(
-    int field_number, const MessageType& value,
-    io::CodedOutputStream* output) {
-  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  output->WriteVarint32(value.MessageType::GetCachedSize());
-  value.MessageType::SerializeWithCachedSizes(output);
-}
-
-// ===================================================================
-
-inline uint8* WireFormat::WriteTagToArray(int field_number,
-                                          WireType type,
-                                          uint8* target) {
-  return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type),
-                                                target);
-}
-
-inline uint8* WireFormat::WriteInt32NoTagToArray(int32 value, uint8* target) {
-  return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
-}
-inline uint8* WireFormat::WriteInt64NoTagToArray(int64 value, uint8* target) {
-  return io::CodedOutputStream::WriteVarint64ToArray(
-      static_cast<uint64>(value), target);
-}
-inline uint8* WireFormat::WriteUInt32NoTagToArray(uint32 value, uint8* target) {
-  return io::CodedOutputStream::WriteVarint32ToArray(value, target);
-}
-inline uint8* WireFormat::WriteUInt64NoTagToArray(uint64 value, uint8* target) {
-  return io::CodedOutputStream::WriteVarint64ToArray(value, target);
-}
-inline uint8* WireFormat::WriteSInt32NoTagToArray(int32 value, uint8* target) {
-  return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value),
-                                                     target);
-}
-inline uint8* WireFormat::WriteSInt64NoTagToArray(int64 value, uint8* target) {
-  return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value),
-                                                     target);
-}
-inline uint8* WireFormat::WriteFixed32NoTagToArray(uint32 value,
-                                                   uint8* target) {
-  return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target);
-}
-inline uint8* WireFormat::WriteFixed64NoTagToArray(uint64 value,
-                                                   uint8* target) {
-  return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target);
-}
-inline uint8* WireFormat::WriteSFixed32NoTagToArray(int32 value,
-                                                    uint8* target) {
-  return io::CodedOutputStream::WriteLittleEndian32ToArray(
-      static_cast<uint32>(value), target);
-}
-inline uint8* WireFormat::WriteSFixed64NoTagToArray(int64 value,
-                                                    uint8* target) {
-  return io::CodedOutputStream::WriteLittleEndian64ToArray(
-      static_cast<uint64>(value), target);
-}
-inline uint8* WireFormat::WriteFloatNoTagToArray(float value, uint8* target) {
-  return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value),
-                                                           target);
-}
-inline uint8* WireFormat::WriteDoubleNoTagToArray(double value,
-                                                  uint8* target) {
-  return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value),
-                                                           target);
-}
-inline uint8* WireFormat::WriteBoolNoTagToArray(bool value,
-                                                uint8* target) {
-  return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target);
-}
-inline uint8* WireFormat::WriteEnumNoTagToArray(int value,
-                                                uint8* target) {
-  return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
-}
-
-inline uint8* WireFormat::WriteInt32ToArray(int field_number,
-                                            int32 value,
-                                            uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteInt32NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteInt64ToArray(int field_number,
-                                            int64 value,
-                                            uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteInt64NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteUInt32ToArray(int field_number,
-                                             uint32 value,
-                                             uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteUInt32NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteUInt64ToArray(int field_number,
-                                             uint64 value,
-                                             uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteUInt64NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteSInt32ToArray(int field_number,
-                                             int32 value,
-                                             uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteSInt32NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteSInt64ToArray(int field_number,
-                                             int64 value,
-                                             uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteSInt64NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteFixed32ToArray(int field_number,
-                                              uint32 value,
-                                              uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
-  return WriteFixed32NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteFixed64ToArray(int field_number,
-                                              uint64 value,
-                                              uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
-  return WriteFixed64NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteSFixed32ToArray(int field_number,
-                                               int32 value,
-                                               uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
-  return WriteSFixed32NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteSFixed64ToArray(int field_number,
-                                               int64 value,
-                                               uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
-  return WriteSFixed64NoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteFloatToArray(int field_number,
-                                            float value,
-                                            uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
-  return WriteFloatNoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteDoubleToArray(int field_number,
-                                             double value,
-                                             uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
-  return WriteDoubleNoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteBoolToArray(int field_number,
-                                           bool value,
-                                           uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteBoolNoTagToArray(value, target);
-}
-inline uint8* WireFormat::WriteEnumToArray(int field_number,
-                                           int value,
-                                           uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
-  return WriteEnumNoTagToArray(value, target);
-}
-
-inline uint8* WireFormat::WriteStringToArray(int field_number,
-                                             const string& value,
-                                             uint8* target) {
-  // String is for UTF-8 text only
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  if (!IsStructurallyValidUTF8(value.data(), value.size())) {
-    GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
-               "serializing protocol buffer. Strings must contain only UTF-8; "
-               "use the 'bytes' type for raw bytes.";
-  }
-#endif
-  // WARNING:  In wire_format.cc, both strings and bytes are handled by
-  //   WriteString() to avoid code duplication.  If the implementations become
-  //   different, you will need to update that usage.
-  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
-  target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target);
-  return io::CodedOutputStream::WriteStringToArray(value, target);
-}
-inline uint8* WireFormat::WriteBytesToArray(int field_number,
-                                            const string& value,
-                                            uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
-  target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target);
-  return io::CodedOutputStream::WriteStringToArray(value, target);
-}
-
-
-inline uint8* WireFormat::WriteGroupToArray(int field_number,
-                                            const Message& value,
-                                            uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
-  target = value.SerializeWithCachedSizesToArray(target);
-  return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
-}
-inline uint8* WireFormat::WriteMessageToArray(int field_number,
-                                              const Message& value,
-                                              uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
-  target = io::CodedOutputStream::WriteVarint32ToArray(
-    value.GetCachedSize(), target);
-  return value.SerializeWithCachedSizesToArray(target);
-}
-
-template<typename MessageType>
-inline uint8* WireFormat::WriteGroupNoVirtualToArray(
-    int field_number, const MessageType& value, uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
-  target = value.MessageType::SerializeWithCachedSizesToArray(target);
-  return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
-}
-template<typename MessageType>
-inline uint8* WireFormat::WriteMessageNoVirtualToArray(
-    int field_number, const MessageType& value, uint8* target) {
-  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
-  target = io::CodedOutputStream::WriteVarint32ToArray(
-    value.MessageType::GetCachedSize(), target);
-  return value.MessageType::SerializeWithCachedSizesToArray(target);
-}
-
-// ===================================================================
-
-inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) {
-  int result = io::CodedOutputStream::VarintSize32(
-    field_number << kTagTypeBits);
-  if (type == FieldDescriptor::TYPE_GROUP) {
-    // Groups have both a start and an end tag.
-    return result * 2;
-  } else {
-    return result;
-  }
-}
-
-inline int WireFormat::Int32Size(int32 value) {
-  return io::CodedOutputStream::VarintSize32SignExtended(value);
-}
-inline int WireFormat::Int64Size(int64 value) {
-  return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value));
-}
-inline int WireFormat::UInt32Size(uint32 value) {
-  return io::CodedOutputStream::VarintSize32(value);
-}
-inline int WireFormat::UInt64Size(uint64 value) {
-  return io::CodedOutputStream::VarintSize64(value);
-}
-inline int WireFormat::SInt32Size(int32 value) {
-  return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value));
-}
-inline int WireFormat::SInt64Size(int64 value) {
-  return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value));
-}
-inline int WireFormat::EnumSize(int value) {
-  return io::CodedOutputStream::VarintSize32SignExtended(value);
-}
-
-inline int WireFormat::StringSize(const string& value) {
-  return io::CodedOutputStream::VarintSize32(value.size()) +
-         value.size();
-}
-inline int WireFormat::BytesSize(const string& value) {
-  return io::CodedOutputStream::VarintSize32(value.size()) +
-         value.size();
-}
-
-
-inline int WireFormat::GroupSize(const Message& value) {
-  return value.ByteSize();
-}
-inline int WireFormat::MessageSize(const Message& value) {
-  int size = value.ByteSize();
-  return io::CodedOutputStream::VarintSize32(size) + size;
-}
-
-template<typename MessageType>
-inline int WireFormat::GroupSizeNoVirtual(const MessageType& value) {
-  return value.MessageType::ByteSize();
-}
-template<typename MessageType>
-inline int WireFormat::MessageSizeNoVirtual(const MessageType& value) {
-  int size = value.MessageType::ByteSize();
-  return io::CodedOutputStream::VarintSize32(size) + size;
-}
-
-}  // namespace internal
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_INL_H__
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
new file mode 100644
index 0000000..bbbf523
--- /dev/null
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -0,0 +1,193 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <stack>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/wire_format_lite_inl.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/unknown_field_set.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+#ifndef _MSC_VER    // MSVC doesn't like definitions of inline constants, GCC
+                    // requires them.
+const int WireFormatLite::kMessageSetItemStartTag;
+const int WireFormatLite::kMessageSetItemEndTag;
+const int WireFormatLite::kMessageSetTypeIdTag;
+const int WireFormatLite::kMessageSetMessageTag;
+
+#endif
+
+const int WireFormatLite::kMessageSetItemTagsSize =
+  io::CodedOutputStream::VarintSize32(kMessageSetItemStartTag) +
+  io::CodedOutputStream::VarintSize32(kMessageSetItemEndTag) +
+  io::CodedOutputStream::VarintSize32(kMessageSetTypeIdTag) +
+  io::CodedOutputStream::VarintSize32(kMessageSetMessageTag);
+
+const WireFormatLite::CppType
+WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
+  static_cast<CppType>(0),  // 0 is reserved for errors
+
+  CPPTYPE_DOUBLE,   // TYPE_DOUBLE
+  CPPTYPE_FLOAT,    // TYPE_FLOAT
+  CPPTYPE_INT64,    // TYPE_INT64
+  CPPTYPE_UINT64,   // TYPE_UINT64
+  CPPTYPE_INT32,    // TYPE_INT32
+  CPPTYPE_UINT64,   // TYPE_FIXED64
+  CPPTYPE_UINT32,   // TYPE_FIXED32
+  CPPTYPE_BOOL,     // TYPE_BOOL
+  CPPTYPE_STRING,   // TYPE_STRING
+  CPPTYPE_MESSAGE,  // TYPE_GROUP
+  CPPTYPE_MESSAGE,  // TYPE_MESSAGE
+  CPPTYPE_STRING,   // TYPE_BYTES
+  CPPTYPE_UINT32,   // TYPE_UINT32
+  CPPTYPE_ENUM,     // TYPE_ENUM
+  CPPTYPE_INT32,    // TYPE_SFIXED32
+  CPPTYPE_INT64,    // TYPE_SFIXED64
+  CPPTYPE_INT32,    // TYPE_SINT32
+  CPPTYPE_INT64,    // TYPE_SINT64
+};
+
+const WireFormatLite::WireType
+WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
+  static_cast<WireFormatLite::WireType>(-1),  // invalid
+  WireFormatLite::WIRETYPE_FIXED64,           // TYPE_DOUBLE
+  WireFormatLite::WIRETYPE_FIXED32,           // TYPE_FLOAT
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_INT64
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_UINT64
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_INT32
+  WireFormatLite::WIRETYPE_FIXED64,           // TYPE_FIXED64
+  WireFormatLite::WIRETYPE_FIXED32,           // TYPE_FIXED32
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_BOOL
+  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,  // TYPE_STRING
+  WireFormatLite::WIRETYPE_START_GROUP,       // TYPE_GROUP
+  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,  // TYPE_MESSAGE
+  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,  // TYPE_BYTES
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_UINT32
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_ENUM
+  WireFormatLite::WIRETYPE_FIXED32,           // TYPE_SFIXED32
+  WireFormatLite::WIRETYPE_FIXED64,           // TYPE_SFIXED64
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_SINT32
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_SINT64
+};
+
+bool WireFormatLite::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  switch (WireFormatLite::GetTagWireType(tag)) {
+    case WireFormatLite::WIRETYPE_VARINT: {
+      uint64 value;
+      if (!input->ReadVarint64(&value)) return false;
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_FIXED64: {
+      uint64 value;
+      if (!input->ReadLittleEndian64(&value)) return false;
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+      uint32 length;
+      if (!input->ReadVarint32(&length)) return false;
+      if (!input->Skip(length)) return false;
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_START_GROUP: {
+      if (!input->IncrementRecursionDepth()) return false;
+      if (!SkipMessage(input)) return false;
+      input->DecrementRecursionDepth();
+      // Check that the ending tag matched the starting tag.
+      if (!input->LastTagWas(WireFormatLite::MakeTag(
+          WireFormatLite::GetTagFieldNumber(tag),
+          WireFormatLite::WIRETYPE_END_GROUP))) {
+        return false;
+      }
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_END_GROUP: {
+      return false;
+    }
+    case WireFormatLite::WIRETYPE_FIXED32: {
+      uint32 value;
+      if (!input->ReadLittleEndian32(&value)) return false;
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
+  while(true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) {
+      // End of input.  This is a valid place to end, so return true.
+      return true;
+    }
+
+    WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
+
+    if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
+      // Must be the end of the message.
+      return true;
+    }
+
+    if (!SkipField(input, tag)) return false;
+  }
+}
+
+bool FieldSkipper::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  return WireFormatLite::SkipField(input, tag);
+}
+
+bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
+  return WireFormatLite::SkipMessage(input);
+}
+
+void FieldSkipper::SkipUnknownEnum(
+    int field_number, int value) {
+  // Nothing.
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
new file mode 100644
index 0000000..9b7a401
--- /dev/null
+++ b/src/google/protobuf/wire_format_lite.h
@@ -0,0 +1,558 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//         atenasio@google.com (Chris Atenasio) (ZigZag transform)
+//         wink@google.com (Wink Saville) (refactored from wire_format.h)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
+
+#include <string>
+#include <google/protobuf/message_lite.h>
+
+namespace google {
+
+namespace protobuf {
+  namespace io {
+    class CodedInputStream;      // coded_stream.h
+    class CodedOutputStream;     // coded_stream.h
+  }
+}
+
+namespace protobuf {
+namespace internal {
+
+// This class is for internal use by the protocol buffer library and by
+// protocol-complier-generated message classes.  It must not be called
+// directly by clients.
+//
+// This class contains helpers for implementing the binary protocol buffer
+// wire format without the need for reflection. Use WireFormat when using
+// reflection.
+//
+// This class is really a namespace that contains only static methods.
+class LIBPROTOBUF_EXPORT WireFormatLite {
+ public:
+
+  // -----------------------------------------------------------------
+  // Helper constants and functions related to the format.  These are
+  // mostly meant for internal and generated code to use.
+
+  // The wire format is composed of a sequence of tag/value pairs, each
+  // of which contains the value of one field (or one element of a repeated
+  // field).  Each tag is encoded as a varint.  The lower bits of the tag
+  // identify its wire type, which specifies the format of the data to follow.
+  // The rest of the bits contain the field number.  Each type of field (as
+  // declared by FieldDescriptor::Type, in descriptor.h) maps to one of
+  // these wire types.  Immediately following each tag is the field's value,
+  // encoded in the format specified by the wire type.  Because the tag
+  // identifies the encoding of this data, it is possible to skip
+  // unrecognized fields for forwards compatibility.
+
+  enum WireType {
+    WIRETYPE_VARINT           = 0,
+    WIRETYPE_FIXED64          = 1,
+    WIRETYPE_LENGTH_DELIMITED = 2,
+    WIRETYPE_START_GROUP      = 3,
+    WIRETYPE_END_GROUP        = 4,
+    WIRETYPE_FIXED32          = 5,
+  };
+
+  // Lite alternative to FieldDescriptor::Type.  Must be kept in sync.
+  enum FieldType {
+    TYPE_DOUBLE         = 1,
+    TYPE_FLOAT          = 2,
+    TYPE_INT64          = 3,
+    TYPE_UINT64         = 4,
+    TYPE_INT32          = 5,
+    TYPE_FIXED64        = 6,
+    TYPE_FIXED32        = 7,
+    TYPE_BOOL           = 8,
+    TYPE_STRING         = 9,
+    TYPE_GROUP          = 10,
+    TYPE_MESSAGE        = 11,
+    TYPE_BYTES          = 12,
+    TYPE_UINT32         = 13,
+    TYPE_ENUM           = 14,
+    TYPE_SFIXED32       = 15,
+    TYPE_SFIXED64       = 16,
+    TYPE_SINT32         = 17,
+    TYPE_SINT64         = 18,
+    MAX_FIELD_TYPE      = 18,
+  };
+
+  // Lite alternative to FieldDescriptor::CppType.  Must be kept in sync.
+  enum CppType {
+    CPPTYPE_INT32       = 1,
+    CPPTYPE_INT64       = 2,
+    CPPTYPE_UINT32      = 3,
+    CPPTYPE_UINT64      = 4,
+    CPPTYPE_DOUBLE      = 5,
+    CPPTYPE_FLOAT       = 6,
+    CPPTYPE_BOOL        = 7,
+    CPPTYPE_ENUM        = 8,
+    CPPTYPE_STRING      = 9,
+    CPPTYPE_MESSAGE     = 10,
+    MAX_CPPTYPE         = 10,
+  };
+
+  // Helper method to get the CppType for a particular Type.
+  static CppType FieldTypeToCppType(FieldType type);
+
+  // Given a FieldSescriptor::Type return its WireType
+  static inline WireFormatLite::WireType WireTypeForFieldType(
+      WireFormatLite::FieldType type) {
+    return kWireTypeForFieldType[type];
+  }
+
+  // Number of bits in a tag which identify the wire type.
+  static const int kTagTypeBits = 3;
+  // Mask for those bits.
+  static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
+
+  // Helper functions for encoding and decoding tags.  (Inlined below and in
+  // _inl.h)
+  //
+  // This is different from MakeTag(field->number(), field->type()) in the case
+  // of packed repeated fields.
+  static uint32 MakeTag(int field_number, WireType type);
+  static WireType GetTagWireType(uint32 tag);
+  static int GetTagFieldNumber(uint32 tag);
+
+  // Compute the byte size of a tag.  For groups, this includes both the start
+  // and end tags.
+  static inline int TagSize(int field_number, WireFormatLite::FieldType type);
+
+  // Skips a field value with the given tag.  The input should start
+  // positioned immediately after the tag.  Skipped values are simply discarded,
+  // not recorded anywhere.  See WireFormat::SkipField() for a version that
+  // records to an UnknownFieldSet.
+  static bool SkipField(io::CodedInputStream* input, uint32 tag);
+
+  // Reads and ignores a message from the input.  Skipped values are simply
+  // discarded, not recorded anywhere.  See WireFormat::SkipMessage() for a
+  // version that records to an UnknownFieldSet.
+  static bool SkipMessage(io::CodedInputStream* input);
+
+// This macro does the same thing as WireFormatLite::MakeTag(), but the
+// result is usable as a compile-time constant, which makes it usable
+// as a switch case or a template input.  WireFormatLite::MakeTag() is more
+// type-safe, though, so prefer it if possible.
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE)                  \
+  static_cast<uint32>(                                                   \
+    ((FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \
+      | (TYPE))
+
+  // These are the tags for the old MessageSet format, which was defined as:
+  //   message MessageSet {
+  //     repeated group Item = 1 {
+  //       required int32 type_id = 2;
+  //       required string message = 3;
+  //     }
+  //   }
+  static const int kMessageSetItemStartTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_START_GROUP);
+  static const int kMessageSetItemEndTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_END_GROUP);
+  static const int kMessageSetTypeIdTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(2, WireFormatLite::WIRETYPE_VARINT);
+  static const int kMessageSetMessageTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(3, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+  // Byte size of all tags of a MessageSet::Item combined.
+  static const int kMessageSetItemTagsSize;
+
+  // Helper functions for converting between floats/doubles and IEEE-754
+  // uint32s/uint64s so that they can be written.  (Assumes your platform
+  // uses IEEE-754 floats.)
+  static uint32 EncodeFloat(float value);
+  static float DecodeFloat(uint32 value);
+  static uint64 EncodeDouble(double value);
+  static double DecodeDouble(uint64 value);
+
+  // Helper functions for mapping signed integers to unsigned integers in
+  // such a way that numbers with small magnitudes will encode to smaller
+  // varints.  If you simply static_cast a negative number to an unsigned
+  // number and varint-encode it, it will always take 10 bytes, defeating
+  // the purpose of varint.  So, for the "sint32" and "sint64" field types,
+  // we ZigZag-encode the values.
+  static uint32 ZigZagEncode32(int32 n);
+  static int32  ZigZagDecode32(uint32 n);
+  static uint64 ZigZagEncode64(int64 n);
+  static int64  ZigZagDecode64(uint64 n);
+
+  // =================================================================
+  // Methods for reading/writing individual field.  The implementations
+  // of these methods are defined in wire_format_lite_inl.h; you must #include
+  // that file to use these.
+
+// Avoid ugly line wrapping
+#define input  io::CodedInputStream*  input
+#define output io::CodedOutputStream* output
+#define field_number int field_number
+#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+
+  // Read fields, not including tags.  The assumption is that you already
+  // read the tag to determine what field to read.
+  static inline bool ReadInt32   (input,  int32* value);
+  static inline bool ReadInt64   (input,  int64* value);
+  static inline bool ReadUInt32  (input, uint32* value);
+  static inline bool ReadUInt64  (input, uint64* value);
+  static inline bool ReadSInt32  (input,  int32* value);
+  static inline bool ReadSInt64  (input,  int64* value);
+  static inline bool ReadFixed32 (input, uint32* value);
+  static inline bool ReadFixed64 (input, uint64* value);
+  static inline bool ReadSFixed32(input,  int32* value);
+  static inline bool ReadSFixed64(input,  int64* value);
+  static inline bool ReadFloat   (input,  float* value);
+  static inline bool ReadDouble  (input, double* value);
+  static inline bool ReadBool    (input,   bool* value);
+  static inline bool ReadEnum    (input,    int* value);
+
+  static inline bool ReadString(input, string* value);
+  static inline bool ReadBytes (input, string* value);
+
+  static inline bool ReadGroup  (field_number, input, MessageLite* value);
+  static inline bool ReadMessage(input, MessageLite* value);
+
+  // Like above, but de-virtualize the call to MergePartialFromCodedStream().
+  // The pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override MergePartialFromCodedStream()).
+  template<typename MessageType>
+  static inline bool ReadGroupNoVirtual(field_number, input,
+                                        MessageType* value);
+  template<typename MessageType>
+  static inline bool ReadMessageNoVirtual(input, MessageType* value);
+
+  // Write a tag.  The Write*() functions typically include the tag, so
+  // normally there's no need to call this unless using the Write*NoTag()
+  // variants.
+  static inline void WriteTag(field_number, WireType type, output) INL;
+
+  // Write fields, without tags.
+  static inline void WriteInt32NoTag   (int32 value, output) INL;
+  static inline void WriteInt64NoTag   (int64 value, output) INL;
+  static inline void WriteUInt32NoTag  (uint32 value, output) INL;
+  static inline void WriteUInt64NoTag  (uint64 value, output) INL;
+  static inline void WriteSInt32NoTag  (int32 value, output) INL;
+  static inline void WriteSInt64NoTag  (int64 value, output) INL;
+  static inline void WriteFixed32NoTag (uint32 value, output) INL;
+  static inline void WriteFixed64NoTag (uint64 value, output) INL;
+  static inline void WriteSFixed32NoTag(int32 value, output) INL;
+  static inline void WriteSFixed64NoTag(int64 value, output) INL;
+  static inline void WriteFloatNoTag   (float value, output) INL;
+  static inline void WriteDoubleNoTag  (double value, output) INL;
+  static inline void WriteBoolNoTag    (bool value, output) INL;
+  static inline void WriteEnumNoTag    (int value, output) INL;
+
+  // Write fields, including tags.
+  static inline void WriteInt32   (field_number,  int32 value, output) INL;
+  static inline void WriteInt64   (field_number,  int64 value, output) INL;
+  static inline void WriteUInt32  (field_number, uint32 value, output) INL;
+  static inline void WriteUInt64  (field_number, uint64 value, output) INL;
+  static inline void WriteSInt32  (field_number,  int32 value, output) INL;
+  static inline void WriteSInt64  (field_number,  int64 value, output) INL;
+  static inline void WriteFixed32 (field_number, uint32 value, output) INL;
+  static inline void WriteFixed64 (field_number, uint64 value, output) INL;
+  static inline void WriteSFixed32(field_number,  int32 value, output) INL;
+  static inline void WriteSFixed64(field_number,  int64 value, output) INL;
+  static inline void WriteFloat   (field_number,  float value, output) INL;
+  static inline void WriteDouble  (field_number, double value, output) INL;
+  static inline void WriteBool    (field_number,   bool value, output) INL;
+  static inline void WriteEnum    (field_number,    int value, output) INL;
+
+  static inline void WriteString(field_number, const string& value, output) INL;
+  static inline void WriteBytes (field_number, const string& value, output) INL;
+
+  static inline void WriteGroup(
+    field_number, const MessageLite& value, output) INL;
+  static inline void WriteMessage(
+    field_number, const MessageLite& value, output) INL;
+
+  // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
+  // pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override SerializeWithCachedSizes()).
+  template<typename MessageType>
+  static inline void WriteGroupNoVirtual(
+    field_number, const MessageType& value, output) INL;
+  template<typename MessageType>
+  static inline void WriteMessageNoVirtual(
+    field_number, const MessageType& value, output) INL;
+
+#undef output
+#define output uint8* target
+
+  // Like above, but use only *ToArray methods of CodedOutputStream.
+  static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
+
+  // Write fields, without tags.
+  static inline uint8* WriteInt32NoTagToArray   (int32 value, output) INL;
+  static inline uint8* WriteInt64NoTagToArray   (int64 value, output) INL;
+  static inline uint8* WriteUInt32NoTagToArray  (uint32 value, output) INL;
+  static inline uint8* WriteUInt64NoTagToArray  (uint64 value, output) INL;
+  static inline uint8* WriteSInt32NoTagToArray  (int32 value, output) INL;
+  static inline uint8* WriteSInt64NoTagToArray  (int64 value, output) INL;
+  static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
+  static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
+  static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
+  static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
+  static inline uint8* WriteFloatNoTagToArray   (float value, output) INL;
+  static inline uint8* WriteDoubleNoTagToArray  (double value, output) INL;
+  static inline uint8* WriteBoolNoTagToArray    (bool value, output) INL;
+  static inline uint8* WriteEnumNoTagToArray    (int value, output) INL;
+
+  // Write fields, including tags.
+  static inline uint8* WriteInt32ToArray(
+    field_number, int32 value, output) INL;
+  static inline uint8* WriteInt64ToArray(
+    field_number, int64 value, output) INL;
+  static inline uint8* WriteUInt32ToArray(
+    field_number, uint32 value, output) INL;
+  static inline uint8* WriteUInt64ToArray(
+    field_number, uint64 value, output) INL;
+  static inline uint8* WriteSInt32ToArray(
+    field_number, int32 value, output) INL;
+  static inline uint8* WriteSInt64ToArray(
+    field_number, int64 value, output) INL;
+  static inline uint8* WriteFixed32ToArray(
+    field_number, uint32 value, output) INL;
+  static inline uint8* WriteFixed64ToArray(
+    field_number, uint64 value, output) INL;
+  static inline uint8* WriteSFixed32ToArray(
+    field_number, int32 value, output) INL;
+  static inline uint8* WriteSFixed64ToArray(
+    field_number, int64 value, output) INL;
+  static inline uint8* WriteFloatToArray(
+    field_number, float value, output) INL;
+  static inline uint8* WriteDoubleToArray(
+    field_number, double value, output) INL;
+  static inline uint8* WriteBoolToArray(
+    field_number, bool value, output) INL;
+  static inline uint8* WriteEnumToArray(
+    field_number, int value, output) INL;
+
+  static inline uint8* WriteStringToArray(
+    field_number, const string& value, output) INL;
+  static inline uint8* WriteBytesToArray(
+    field_number, const string& value, output) INL;
+
+  static inline uint8* WriteGroupToArray(
+      field_number, const MessageLite& value, output) INL;
+  static inline uint8* WriteMessageToArray(
+      field_number, const MessageLite& value, output) INL;
+
+  // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
+  // pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override SerializeWithCachedSizes()).
+  template<typename MessageType>
+  static inline uint8* WriteGroupNoVirtualToArray(
+    field_number, const MessageType& value, output) INL;
+  template<typename MessageType>
+  static inline uint8* WriteMessageNoVirtualToArray(
+    field_number, const MessageType& value, output) INL;
+
+#undef output
+#undef input
+#undef INL
+
+#undef field_number
+
+  // Compute the byte size of a field.  The XxSize() functions do NOT include
+  // the tag, so you must also call TagSize().  (This is because, for repeated
+  // fields, you should only call TagSize() once and multiply it by the element
+  // count, but you may have to call XxSize() for each individual element.)
+  static inline int Int32Size   ( int32 value);
+  static inline int Int64Size   ( int64 value);
+  static inline int UInt32Size  (uint32 value);
+  static inline int UInt64Size  (uint64 value);
+  static inline int SInt32Size  ( int32 value);
+  static inline int SInt64Size  ( int64 value);
+  static inline int EnumSize    (   int value);
+
+  // These types always have the same size.
+  static const int kFixed32Size  = 4;
+  static const int kFixed64Size  = 8;
+  static const int kSFixed32Size = 4;
+  static const int kSFixed64Size = 8;
+  static const int kFloatSize    = 4;
+  static const int kDoubleSize   = 8;
+  static const int kBoolSize     = 1;
+
+  static inline int StringSize(const string& value);
+  static inline int BytesSize (const string& value);
+
+  static inline int GroupSize  (const MessageLite& value);
+  static inline int MessageSize(const MessageLite& value);
+
+  // Like above, but de-virtualize the call to ByteSize().  The
+  // pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override ByteSize()).
+  template<typename MessageType>
+  static inline int GroupSizeNoVirtual  (const MessageType& value);
+  template<typename MessageType>
+  static inline int MessageSizeNoVirtual(const MessageType& value);
+
+ private:
+  static const CppType kFieldTypeToCppTypeMap[];
+  static const WireFormatLite::WireType kWireTypeForFieldType[];
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
+};
+
+// A class which deals with unknown values.  The default implementation just
+// discards them.  WireFormat defines a subclass which writes to an
+// UnknownFieldSet.  This class is used by ExtensionSet::ParseField(), since
+// ExtensionSet is part of the lite library but UnknownFieldSet is not.
+class LIBPROTOBUF_EXPORT FieldSkipper {
+ public:
+  FieldSkipper() {}
+  virtual ~FieldSkipper() {}
+
+  // Skip a field whose tag has already been consumed.
+  virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
+
+  // Skip an entire message or group, up to an end-group tag (which is consumed)
+  // or end-of-stream.
+  virtual bool SkipMessage(io::CodedInputStream* input);
+
+  // Deal with an already-parsed unrecognized enum value.  The default
+  // implementation does nothing, but the UnknownFieldSet-based implementation
+  // saves it as an unknown varint.
+  virtual void SkipUnknownEnum(int field_number, int value);
+};
+
+// inline methods ====================================================
+
+inline WireFormatLite::CppType
+WireFormatLite::FieldTypeToCppType(FieldType type) {
+  return kFieldTypeToCppTypeMap[type];
+}
+
+inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) {
+  return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
+}
+
+inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) {
+  return static_cast<WireType>(tag & kTagTypeMask);
+}
+
+inline int WireFormatLite::GetTagFieldNumber(uint32 tag) {
+  return static_cast<int>(tag >> kTagTypeBits);
+}
+
+inline int WireFormatLite::TagSize(int field_number,
+                                   WireFormatLite::FieldType type) {
+  int result = io::CodedOutputStream::VarintSize32(
+    field_number << kTagTypeBits);
+  if (type == TYPE_GROUP) {
+    // Groups have both a start and an end tag.
+    return result * 2;
+  } else {
+    return result;
+  }
+}
+
+inline uint32 WireFormatLite::EncodeFloat(float value) {
+  union {float f; uint32 i;};
+  f = value;
+  return i;
+}
+
+inline float WireFormatLite::DecodeFloat(uint32 value) {
+  union {float f; uint32 i;};
+  i = value;
+  return f;
+}
+
+inline uint64 WireFormatLite::EncodeDouble(double value) {
+  union {double f; uint64 i;};
+  f = value;
+  return i;
+}
+
+inline double WireFormatLite::DecodeDouble(uint64 value) {
+  union {double f; uint64 i;};
+  i = value;
+  return f;
+}
+
+// ZigZag Transform:  Encodes signed integers so that they can be
+// effectively used with varint encoding.
+//
+// varint operates on unsigned integers, encoding smaller numbers into
+// fewer bytes.  If you try to use it on a signed integer, it will treat
+// this number as a very large unsigned integer, which means that even
+// small signed numbers like -1 will take the maximum number of bytes
+// (10) to encode.  ZigZagEncode() maps signed integers to unsigned
+// in such a way that those with a small absolute value will have smaller
+// encoded values, making them appropriate for encoding using varint.
+//
+//       int32 ->     uint32
+// -------------------------
+//           0 ->          0
+//          -1 ->          1
+//           1 ->          2
+//          -2 ->          3
+//         ... ->        ...
+//  2147483647 -> 4294967294
+// -2147483648 -> 4294967295
+//
+//        >> encode >>
+//        << decode <<
+
+inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
+  // Note:  the right-shift must be arithmetic
+  return (n << 1) ^ (n >> 31);
+}
+
+inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
+  return (n >> 1) ^ -static_cast<int32>(n & 1);
+}
+
+inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
+  // Note:  the right-shift must be arithmetic
+  return (n << 1) ^ (n >> 63);
+}
+
+inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
+  return (n >> 1) ^ -static_cast<int64>(n & 1);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
new file mode 100644
index 0000000..eb9155e
--- /dev/null
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -0,0 +1,657 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//         wink@google.com (Wink Saville) (refactored from wire_format.h)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/io/coded_stream.h>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline bool WireFormatLite::ReadInt32(io::CodedInputStream* input,
+                                      int32* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = static_cast<int32>(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadInt64(io::CodedInputStream* input,
+                                      int64* value) {
+  uint64 temp;
+  if (!input->ReadVarint64(&temp)) return false;
+  *value = static_cast<int64>(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadUInt32(io::CodedInputStream* input,
+                                       uint32* value) {
+  return input->ReadVarint32(value);
+}
+inline bool WireFormatLite::ReadUInt64(io::CodedInputStream* input,
+                                       uint64* value) {
+  return input->ReadVarint64(value);
+}
+inline bool WireFormatLite::ReadSInt32(io::CodedInputStream* input,
+                                       int32* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = ZigZagDecode32(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadSInt64(io::CodedInputStream* input,
+                                       int64* value) {
+  uint64 temp;
+  if (!input->ReadVarint64(&temp)) return false;
+  *value = ZigZagDecode64(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadFixed32(io::CodedInputStream* input,
+                                        uint32* value) {
+  return input->ReadLittleEndian32(value);
+}
+inline bool WireFormatLite::ReadFixed64(io::CodedInputStream* input,
+                                        uint64* value) {
+  return input->ReadLittleEndian64(value);
+}
+inline bool WireFormatLite::ReadSFixed32(io::CodedInputStream* input,
+                                         int32* value) {
+  uint32 temp;
+  if (!input->ReadLittleEndian32(&temp)) return false;
+  *value = static_cast<int32>(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadSFixed64(io::CodedInputStream* input,
+                                         int64* value) {
+  uint64 temp;
+  if (!input->ReadLittleEndian64(&temp)) return false;
+  *value = static_cast<int64>(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadFloat(io::CodedInputStream* input,
+                                      float* value) {
+  uint32 temp;
+  if (!input->ReadLittleEndian32(&temp)) return false;
+  *value = DecodeFloat(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadDouble(io::CodedInputStream* input,
+                                       double* value) {
+  uint64 temp;
+  if (!input->ReadLittleEndian64(&temp)) return false;
+  *value = DecodeDouble(temp);
+  return true;
+}
+inline bool WireFormatLite::ReadBool(io::CodedInputStream* input,
+                                     bool* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = temp != 0;
+  return true;
+}
+inline bool WireFormatLite::ReadEnum(io::CodedInputStream* input,
+                                     int* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = static_cast<int>(temp);
+  return true;
+}
+
+inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
+                                       string* value) {
+  // String is for UTF-8 text only
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  if (!input->ReadString(value, length)) return false;
+  return true;
+}
+inline bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
+                                      string* value) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  return input->ReadString(value, length);
+}
+
+
+inline bool WireFormatLite::ReadGroup(int field_number,
+                                      io::CodedInputStream* input,
+                                      MessageLite* value) {
+  if (!input->IncrementRecursionDepth()) return false;
+  if (!value->MergePartialFromCodedStream(input)) return false;
+  input->DecrementRecursionDepth();
+  // Make sure the last thing read was an end tag for this group.
+  if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
+    return false;
+  }
+  return true;
+}
+inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input,
+                                        MessageLite* value) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  if (!input->IncrementRecursionDepth()) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  if (!value->MergePartialFromCodedStream(input)) return false;
+  // Make sure that parsing stopped when the limit was hit, not at an endgroup
+  // tag.
+  if (!input->ConsumedEntireMessage()) return false;
+  input->PopLimit(limit);
+  input->DecrementRecursionDepth();
+  return true;
+}
+
+template<typename MessageType>
+inline bool WireFormatLite::ReadGroupNoVirtual(int field_number,
+                                               io::CodedInputStream* input,
+                                               MessageType* value) {
+  if (!input->IncrementRecursionDepth()) return false;
+  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
+  input->DecrementRecursionDepth();
+  // Make sure the last thing read was an end tag for this group.
+  if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
+    return false;
+  }
+  return true;
+}
+template<typename MessageType>
+inline bool WireFormatLite::ReadMessageNoVirtual(io::CodedInputStream* input,
+                                                 MessageType* value) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  if (!input->IncrementRecursionDepth()) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
+  // Make sure that parsing stopped when the limit was hit, not at an endgroup
+  // tag.
+  if (!input->ConsumedEntireMessage()) return false;
+  input->PopLimit(limit);
+  input->DecrementRecursionDepth();
+  return true;
+}
+
+// ===================================================================
+
+inline void WireFormatLite::WriteTag(int field_number, WireType type,
+                                     io::CodedOutputStream* output) {
+  output->WriteTag(MakeTag(field_number, type));
+}
+
+inline void WireFormatLite::WriteInt32NoTag(int32 value,
+                                            io::CodedOutputStream* output) {
+  output->WriteVarint32SignExtended(value);
+}
+inline void WireFormatLite::WriteInt64NoTag(int64 value,
+                                            io::CodedOutputStream* output) {
+  output->WriteVarint64(static_cast<uint64>(value));
+}
+inline void WireFormatLite::WriteUInt32NoTag(uint32 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint32(value);
+}
+inline void WireFormatLite::WriteUInt64NoTag(uint64 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint64(value);
+}
+inline void WireFormatLite::WriteSInt32NoTag(int32 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint32(ZigZagEncode32(value));
+}
+inline void WireFormatLite::WriteSInt64NoTag(int64 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint64(ZigZagEncode64(value));
+}
+inline void WireFormatLite::WriteFixed32NoTag(uint32 value,
+                                              io::CodedOutputStream* output) {
+  output->WriteLittleEndian32(value);
+}
+inline void WireFormatLite::WriteFixed64NoTag(uint64 value,
+                                              io::CodedOutputStream* output) {
+  output->WriteLittleEndian64(value);
+}
+inline void WireFormatLite::WriteSFixed32NoTag(int32 value,
+                                               io::CodedOutputStream* output) {
+  output->WriteLittleEndian32(static_cast<uint32>(value));
+}
+inline void WireFormatLite::WriteSFixed64NoTag(int64 value,
+                                               io::CodedOutputStream* output) {
+  output->WriteLittleEndian64(static_cast<uint64>(value));
+}
+inline void WireFormatLite::WriteFloatNoTag(float value,
+                                            io::CodedOutputStream* output) {
+  output->WriteLittleEndian32(EncodeFloat(value));
+}
+inline void WireFormatLite::WriteDoubleNoTag(double value,
+                                             io::CodedOutputStream* output) {
+  output->WriteLittleEndian64(EncodeDouble(value));
+}
+inline void WireFormatLite::WriteBoolNoTag(bool value,
+                                           io::CodedOutputStream* output) {
+  output->WriteVarint32(value ? 1 : 0);
+}
+inline void WireFormatLite::WriteEnumNoTag(int value,
+                                           io::CodedOutputStream* output) {
+  output->WriteVarint32SignExtended(value);
+}
+
+inline void WireFormatLite::WriteInt32(int field_number, int32 value,
+                                       io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteInt32NoTag(value, output);
+}
+inline void WireFormatLite::WriteInt64(int field_number, int64 value,
+                                       io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteInt64NoTag(value, output);
+}
+inline void WireFormatLite::WriteUInt32(int field_number, uint32 value,
+                                        io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteUInt32NoTag(value, output);
+}
+inline void WireFormatLite::WriteUInt64(int field_number, uint64 value,
+                                        io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteUInt64NoTag(value, output);
+}
+inline void WireFormatLite::WriteSInt32(int field_number, int32 value,
+                                        io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteSInt32NoTag(value, output);
+}
+inline void WireFormatLite::WriteSInt64(int field_number, int64 value,
+                                        io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteSInt64NoTag(value, output);
+}
+inline void WireFormatLite::WriteFixed32(int field_number, uint32 value,
+                                         io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED32, output);
+  WriteFixed32NoTag(value, output);
+}
+inline void WireFormatLite::WriteFixed64(int field_number, uint64 value,
+                                         io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED64, output);
+  WriteFixed64NoTag(value, output);
+}
+inline void WireFormatLite::WriteSFixed32(int field_number, int32 value,
+                                          io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED32, output);
+  WriteSFixed32NoTag(value, output);
+}
+inline void WireFormatLite::WriteSFixed64(int field_number, int64 value,
+                                          io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED64, output);
+  WriteSFixed64NoTag(value, output);
+}
+inline void WireFormatLite::WriteFloat(int field_number, float value,
+                                       io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED32, output);
+  WriteFloatNoTag(value, output);
+}
+inline void WireFormatLite::WriteDouble(int field_number, double value,
+                                        io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED64, output);
+  WriteDoubleNoTag(value, output);
+}
+inline void WireFormatLite::WriteBool(int field_number, bool value,
+                                      io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteBoolNoTag(value, output);
+}
+inline void WireFormatLite::WriteEnum(int field_number, int value,
+                                      io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteEnumNoTag(value, output);
+}
+
+inline void WireFormatLite::WriteString(int field_number, const string& value,
+                                        io::CodedOutputStream* output) {
+  // String is for UTF-8 text only
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  output->WriteVarint32(value.size());
+  output->WriteString(value);
+}
+inline void WireFormatLite::WriteBytes(int field_number, const string& value,
+                                       io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  output->WriteVarint32(value.size());
+  output->WriteString(value);
+}
+
+
+inline void WireFormatLite::WriteGroup(int field_number,
+                                       const MessageLite& value,
+                                       io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_START_GROUP, output);
+  value.SerializeWithCachedSizes(output);
+  WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+inline void WireFormatLite::WriteMessage(int field_number,
+                                         const MessageLite& value,
+                                         io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  output->WriteVarint32(value.GetCachedSize());
+  value.SerializeWithCachedSizes(output);
+}
+
+template<typename MessageType>
+inline void WireFormatLite::WriteGroupNoVirtual(int field_number,
+                                                const MessageType& value,
+                                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_START_GROUP, output);
+  value.MessageType::SerializeWithCachedSizes(output);
+  WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+template<typename MessageType>
+inline void WireFormatLite::WriteMessageNoVirtual(int field_number,
+                                                const MessageType& value,
+                                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  output->WriteVarint32(value.MessageType::GetCachedSize());
+  value.MessageType::SerializeWithCachedSizes(output);
+}
+
+// ===================================================================
+
+inline uint8* WireFormatLite::WriteTagToArray(int field_number,
+                                              WireType type,
+                                              uint8* target) {
+  return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type),
+                                                target);
+}
+
+inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value,
+                                                     uint8* target) {
+  return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value,
+                                                     uint8* target) {
+  return io::CodedOutputStream::WriteVarint64ToArray(
+      static_cast<uint64>(value), target);
+}
+inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint32ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint64ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value),
+                                                     target);
+}
+inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value),
+                                                     target);
+}
+inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value,
+                                                       uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value,
+                                                       uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value,
+                                                        uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian32ToArray(
+      static_cast<uint32>(value), target);
+}
+inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value,
+                                                        uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian64ToArray(
+      static_cast<uint64>(value), target);
+}
+inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value,
+                                                     uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value),
+                                                           target);
+}
+inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value),
+                                                           target);
+}
+inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value,
+                                                    uint8* target) {
+  return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target);
+}
+inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value,
+                                                    uint8* target) {
+  return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
+}
+
+inline uint8* WireFormatLite::WriteInt32ToArray(int field_number,
+                                                int32 value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteInt64ToArray(int field_number,
+                                                int64 value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number,
+                                                 uint32 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteUInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number,
+                                                 uint64 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteUInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number,
+                                                 int32 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteSInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number,
+                                                 int64 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteSInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number,
+                                                  uint32 value,
+                                                  uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+  return WriteFixed32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number,
+                                                  uint64 value,
+                                                  uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+  return WriteFixed64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number,
+                                                   int32 value,
+                                                   uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+  return WriteSFixed32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number,
+                                                   int64 value,
+                                                   uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+  return WriteSFixed64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFloatToArray(int field_number,
+                                                float value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+  return WriteFloatNoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteDoubleToArray(int field_number,
+                                                 double value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+  return WriteDoubleNoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteBoolToArray(int field_number,
+                                               bool value,
+                                               uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteBoolNoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteEnumToArray(int field_number,
+                                               int value,
+                                               uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteEnumNoTagToArray(value, target);
+}
+
+inline uint8* WireFormatLite::WriteStringToArray(int field_number,
+                                                 const string& value,
+                                                 uint8* target) {
+  // String is for UTF-8 text only
+  // WARNING:  In wire_format.cc, both strings and bytes are handled by
+  //   WriteString() to avoid code duplication.  If the implementations become
+  //   different, you will need to update that usage.
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target);
+  return io::CodedOutputStream::WriteStringToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteBytesToArray(int field_number,
+                                                const string& value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target);
+  return io::CodedOutputStream::WriteStringToArray(value, target);
+}
+
+
+inline uint8* WireFormatLite::WriteGroupToArray(int field_number,
+                                                const MessageLite& value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
+  target = value.SerializeWithCachedSizesToArray(target);
+  return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
+}
+inline uint8* WireFormatLite::WriteMessageToArray(int field_number,
+                                                  const MessageLite& value,
+                                                  uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  target = io::CodedOutputStream::WriteVarint32ToArray(
+    value.GetCachedSize(), target);
+  return value.SerializeWithCachedSizesToArray(target);
+}
+
+template<typename MessageType>
+inline uint8* WireFormatLite::WriteGroupNoVirtualToArray(
+    int field_number, const MessageType& value, uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
+  target = value.MessageType::SerializeWithCachedSizesToArray(target);
+  return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
+}
+template<typename MessageType>
+inline uint8* WireFormatLite::WriteMessageNoVirtualToArray(
+    int field_number, const MessageType& value, uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  target = io::CodedOutputStream::WriteVarint32ToArray(
+    value.MessageType::GetCachedSize(), target);
+  return value.MessageType::SerializeWithCachedSizesToArray(target);
+}
+
+// ===================================================================
+
+inline int WireFormatLite::Int32Size(int32 value) {
+  return io::CodedOutputStream::VarintSize32SignExtended(value);
+}
+inline int WireFormatLite::Int64Size(int64 value) {
+  return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value));
+}
+inline int WireFormatLite::UInt32Size(uint32 value) {
+  return io::CodedOutputStream::VarintSize32(value);
+}
+inline int WireFormatLite::UInt64Size(uint64 value) {
+  return io::CodedOutputStream::VarintSize64(value);
+}
+inline int WireFormatLite::SInt32Size(int32 value) {
+  return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value));
+}
+inline int WireFormatLite::SInt64Size(int64 value) {
+  return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value));
+}
+inline int WireFormatLite::EnumSize(int value) {
+  return io::CodedOutputStream::VarintSize32SignExtended(value);
+}
+
+inline int WireFormatLite::StringSize(const string& value) {
+  return io::CodedOutputStream::VarintSize32(value.size()) +
+         value.size();
+}
+inline int WireFormatLite::BytesSize(const string& value) {
+  return io::CodedOutputStream::VarintSize32(value.size()) +
+         value.size();
+}
+
+
+inline int WireFormatLite::GroupSize(const MessageLite& value) {
+  return value.ByteSize();
+}
+inline int WireFormatLite::MessageSize(const MessageLite& value) {
+  int size = value.ByteSize();
+  return io::CodedOutputStream::VarintSize32(size) + size;
+}
+
+template<typename MessageType>
+inline int WireFormatLite::GroupSizeNoVirtual(const MessageType& value) {
+  return value.MessageType::ByteSize();
+}
+template<typename MessageType>
+inline int WireFormatLite::MessageSizeNoVirtual(const MessageType& value) {
+  int size = value.MessageType::ByteSize();
+  return io::CodedOutputStream::VarintSize32(size) + size;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 6352b0a..51960ee 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -33,7 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_inl.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/coded_stream.h>
@@ -51,9 +51,27 @@
 namespace internal {
 namespace {
 
+TEST(WireFormatTest, EnumsInSync) {
+  // Verify that WireFormatLite::FieldType and WireFormatLite::CppType match
+  // FieldDescriptor::Type and FieldDescriptor::CppType.
+
+  EXPECT_EQ(implicit_cast<int>(FieldDescriptor::MAX_TYPE),
+            implicit_cast<int>(WireFormatLite::MAX_FIELD_TYPE));
+  EXPECT_EQ(implicit_cast<int>(FieldDescriptor::MAX_CPPTYPE),
+            implicit_cast<int>(WireFormatLite::MAX_CPPTYPE));
+
+  for (int i = 1; i <= WireFormatLite::MAX_FIELD_TYPE; i++) {
+    EXPECT_EQ(
+      implicit_cast<int>(FieldDescriptor::TypeToCppType(
+        static_cast<FieldDescriptor::Type>(i))),
+      implicit_cast<int>(WireFormatLite::FieldTypeToCppType(
+        static_cast<WireFormatLite::FieldType>(i))));
+  }
+}
+
 TEST(WireFormatTest, MaxFieldNumber) {
   // Make sure the max field number constant is accurate.
-  EXPECT_EQ((1 << (32 - WireFormat::kTagTypeBits)) - 1,
+  EXPECT_EQ((1 << (32 - WireFormatLite::kTagTypeBits)) - 1,
             FieldDescriptor::kMaxNumber);
 }
 
@@ -326,9 +344,9 @@
   EXPECT_EQ("bar", raw.item(2).message());
 }
 
-TEST(WireFormatTest, SerializeMessageSetToStreamAndArrayAreEqual) {
-  // Serialize a MessageSet to a stream and to a flat array and check that the
-  // results are equal.
+TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) {
+  // Serialize a MessageSet to a stream and to a flat array using generated
+  // code, and also using WireFormat, and check that the results are equal.
   // Set up a TestMessageSet with two known messages and an unknown one, as
   // above.
 
@@ -341,10 +359,15 @@
     kUnknownTypeId, "bar");
 
   int size = message_set.ByteSize();
+  EXPECT_EQ(size, message_set.GetCachedSize());
+  ASSERT_EQ(size, WireFormat::ByteSize(message_set));
+
   string flat_data;
   string stream_data;
+  string dynamic_data;
   flat_data.resize(size);
   stream_data.resize(size);
+
   // Serialize to flat array
   {
     uint8* target = reinterpret_cast<uint8*>(string_as_array(&flat_data));
@@ -360,7 +383,16 @@
     ASSERT_FALSE(output_stream.HadError());
   }
 
+  // Serialize to buffer with WireFormat.
+  {
+    io::StringOutputStream string_stream(&dynamic_data);
+    io::CodedOutputStream output_stream(&string_stream);
+    WireFormat::SerializeWithCachedSizes(message_set, size, &output_stream);
+    ASSERT_FALSE(output_stream.HadError());
+  }
+
   EXPECT_TRUE(flat_data == stream_data);
+  EXPECT_TRUE(flat_data == dynamic_data);
 }
 
 TEST(WireFormatTest, ParseMessageSet) {
@@ -407,6 +439,13 @@
   ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED,
             message_set.unknown_fields().field(0).type());
   EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited());
+
+  // Also parse using WireFormat.
+  unittest::TestMessageSet dynamic_message_set;
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(data.data()),
+                             data.size());
+  ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set));
+  EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString());
 }
 
 TEST(WireFormatTest, RecursionLimit) {
@@ -464,10 +503,10 @@
 // avoid line-wrapping
 #define LL(x) GOOGLE_LONGLONG(x)
 #define ULL(x) GOOGLE_ULONGLONG(x)
-#define ZigZagEncode32(x) WireFormat::ZigZagEncode32(x)
-#define ZigZagDecode32(x) WireFormat::ZigZagDecode32(x)
-#define ZigZagEncode64(x) WireFormat::ZigZagEncode64(x)
-#define ZigZagDecode64(x) WireFormat::ZigZagDecode64(x)
+#define ZigZagEncode32(x) WireFormatLite::ZigZagEncode32(x)
+#define ZigZagDecode32(x) WireFormatLite::ZigZagDecode32(x)
+#define ZigZagEncode64(x) WireFormatLite::ZigZagEncode64(x)
+#define ZigZagDecode64(x) WireFormatLite::ZigZagDecode64(x)
 
   EXPECT_EQ(0u, ZigZagEncode32( 0));
   EXPECT_EQ(1u, ZigZagEncode32(-1));
@@ -545,7 +584,7 @@
       io::StringOutputStream raw_output(&result);
       io::CodedOutputStream output(&raw_output);
 
-      WireFormat::WriteBytes(field->number(), string(bytes, size), &output);
+      WireFormatLite::WriteBytes(field->number(), string(bytes, size), &output);
     }
 
     return result;
@@ -569,8 +608,8 @@
       output.WriteVarint32(WireFormat::MakeTag(field));
       output.WriteString(string(bytes, size));
       if (include_end_tag) {
-        output.WriteVarint32(WireFormat::MakeTag(
-          field->number(), WireFormat::WIRETYPE_END_GROUP));
+        output.WriteVarint32(WireFormatLite::MakeTag(
+          field->number(), WireFormatLite::WIRETYPE_END_GROUP));
       }
     }