Explorar o código

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

kenton@google.com %!s(int64=16) %!d(string=hai) anos
pai
achega
80b1d62bfc
Modificáronse 100 ficheiros con 9918 adicións e 4337 borrados
  1. 25 1
      CHANGES.txt
  2. 7 0
      Makefile.am
  3. 5 1
      generate_descriptor_proto.sh
  4. 3 0
      java/pom.xml
  5. 457 224
      java/src/main/java/com/google/protobuf/AbstractMessage.java
  6. 321 0
      java/src/main/java/com/google/protobuf/AbstractMessageLite.java
  7. 39 37
      java/src/main/java/com/google/protobuf/ByteString.java
  8. 95 129
      java/src/main/java/com/google/protobuf/CodedInputStream.java
  9. 174 240
      java/src/main/java/com/google/protobuf/CodedOutputStream.java
  10. 246 184
      java/src/main/java/com/google/protobuf/Descriptors.java
  11. 52 29
      java/src/main/java/com/google/protobuf/DynamicMessage.java
  12. 45 35
      java/src/main/java/com/google/protobuf/ExtensionRegistry.java
  13. 169 0
      java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
  14. 449 461
      java/src/main/java/com/google/protobuf/FieldSet.java
  15. 249 224
      java/src/main/java/com/google/protobuf/GeneratedMessage.java
  16. 539 0
      java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  17. 194 0
      java/src/main/java/com/google/protobuf/Internal.java
  18. 3 1
      java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
  19. 31 216
      java/src/main/java/com/google/protobuf/Message.java
  20. 331 0
      java/src/main/java/com/google/protobuf/MessageLite.java
  21. 1 1
      java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
  22. 8 5
      java/src/main/java/com/google/protobuf/RpcUtil.java
  23. 4 2
      java/src/main/java/com/google/protobuf/ServiceException.java
  24. 164 132
      java/src/main/java/com/google/protobuf/TextFormat.java
  25. 12 73
      java/src/main/java/com/google/protobuf/UninitializedMessageException.java
  26. 274 115
      java/src/main/java/com/google/protobuf/UnknownFieldSet.java
  27. 62 32
      java/src/main/java/com/google/protobuf/WireFormat.java
  28. 30 0
      java/src/test/java/com/google/protobuf/DescriptorsTest.java
  29. 12 0
      java/src/test/java/com/google/protobuf/DynamicMessageTest.java
  30. 89 0
      java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
  31. 114 0
      java/src/test/java/com/google/protobuf/LiteTest.java
  32. 945 86
      java/src/test/java/com/google/protobuf/TestUtil.java
  33. 22 3
      java/src/test/java/com/google/protobuf/TextFormatTest.java
  34. 65 0
      java/src/test/java/com/google/protobuf/WireFormatTest.java
  35. 6 2
      python/google/protobuf/internal/containers.py
  36. 2 2
      python/google/protobuf/internal/decoder.py
  37. 11 7
      python/google/protobuf/internal/decoder_test.py
  38. 4 2
      python/google/protobuf/internal/encoder.py
  39. 8 4
      python/google/protobuf/internal/encoder_test.py
  40. 53 0
      python/google/protobuf/internal/message_test.py
  41. 84 4
      python/google/protobuf/internal/reflection_test.py
  42. 197 1
      python/google/protobuf/internal/test_util.py
  43. 278 3
      python/google/protobuf/internal/text_format_test.py
  44. 4 2
      python/google/protobuf/internal/type_checkers.py
  45. 2 0
      python/google/protobuf/internal/wire_format.py
  46. 1 2
      python/google/protobuf/message.py
  47. 56 10
      python/google/protobuf/reflection.py
  48. 3 2
      python/google/protobuf/service.py
  49. 526 1
      python/google/protobuf/text_format.py
  50. 34 3
      src/Makefile.am
  51. 22 0
      src/google/protobuf/compiler/code_generator.cc
  52. 11 0
      src/google/protobuf/compiler/code_generator.h
  53. 51 28
      src/google/protobuf/compiler/cpp/cpp_enum.cc
  54. 4 0
      src/google/protobuf/compiler/cpp/cpp_enum.h
  55. 52 55
      src/google/protobuf/compiler/cpp/cpp_enum_field.cc
  56. 1 0
      src/google/protobuf/compiler/cpp/cpp_extension.cc
  57. 19 0
      src/google/protobuf/compiler/cpp/cpp_field.cc
  58. 10 0
      src/google/protobuf/compiler/cpp/cpp_field.h
  59. 183 132
      src/google/protobuf/compiler/cpp/cpp_file.cc
  60. 1 28
      src/google/protobuf/compiler/cpp/cpp_generator.cc
  61. 12 1
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  62. 29 0
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  63. 335 188
      src/google/protobuf/compiler/cpp/cpp_message.cc
  64. 4 5
      src/google/protobuf/compiler/cpp/cpp_message.h
  65. 29 38
      src/google/protobuf/compiler/cpp/cpp_message_field.cc
  66. 50 61
      src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
  67. 1 1
      src/google/protobuf/compiler/cpp/cpp_service.cc
  68. 84 45
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  69. 50 14
      src/google/protobuf/compiler/cpp/cpp_unittest.cc
  70. 84 64
      src/google/protobuf/compiler/java/java_enum.cc
  71. 26 17
      src/google/protobuf/compiler/java/java_enum_field.cc
  72. 85 14
      src/google/protobuf/compiler/java/java_extension.cc
  73. 38 5
      src/google/protobuf/compiler/java/java_file.cc
  74. 2 0
      src/google/protobuf/compiler/java/java_file.h
  75. 1 27
      src/google/protobuf/compiler/java/java_generator.cc
  76. 67 0
      src/google/protobuf/compiler/java/java_helpers.cc
  77. 30 0
      src/google/protobuf/compiler/java/java_helpers.h
  78. 300 178
      src/google/protobuf/compiler/java/java_message.cc
  79. 22 81
      src/google/protobuf/compiler/java/java_primitive_field.cc
  80. 1 1
      src/google/protobuf/compiler/parser.cc
  81. 66 14
      src/google/protobuf/descriptor.cc
  82. 284 196
      src/google/protobuf/descriptor.pb.cc
  83. 125 72
      src/google/protobuf/descriptor.pb.h
  84. 9 2
      src/google/protobuf/descriptor.proto
  85. 145 0
      src/google/protobuf/descriptor_unittest.cc
  86. 43 41
      src/google/protobuf/dynamic_message.cc
  87. 361 232
      src/google/protobuf/extension_set.cc
  88. 97 47
      src/google/protobuf/extension_set.h
  89. 218 0
      src/google/protobuf/extension_set_heavy.cc
  90. 243 58
      src/google/protobuf/generated_message_reflection.cc
  91. 10 12
      src/google/protobuf/generated_message_reflection.h
  92. 44 0
      src/google/protobuf/generated_message_util.cc
  93. 65 0
      src/google/protobuf/generated_message_util.h
  94. 46 50
      src/google/protobuf/io/coded_stream.cc
  95. 46 0
      src/google/protobuf/io/coded_stream.h
  96. 3 4
      src/google/protobuf/io/gzip_stream.cc
  97. 2 4
      src/google/protobuf/io/gzip_stream.h
  98. 1 1
      src/google/protobuf/io/tokenizer.cc
  99. 1 0
      src/google/protobuf/io/tokenizer_unittest.cc
  100. 0 345
      src/google/protobuf/io/zero_copy_stream_impl.cc

+ 25 - 1
CHANGES.txt

@@ -1,6 +1,9 @@
-????-??-?? version 2.1.1:
+????-??-?? version 2.2.0:
 
 
   C++
   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
   * Fixed bug where Message.Swap(Message) was only implemented for
     optimize_for_speed.  Swap now properly implemented in both modes
     optimize_for_speed.  Swap now properly implemented in both modes
     (Issue 91).
     (Issue 91).
@@ -10,6 +13,27 @@
   * Floating-point literals in generated code that are intended to be
   * Floating-point literals in generated code that are intended to be
     single-precision now explicitly have 'f' suffix to avoid pedantic warnings
     single-precision now explicitly have 'f' suffix to avoid pedantic warnings
     produced by some compilers.
     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:
 2009-05-13 version 2.1.0:
 
 

+ 7 - 0
Makefile.am

@@ -62,6 +62,7 @@ EXTRA_DIST =                                                                 \
   examples/add_person.py                                                     \
   examples/add_person.py                                                     \
   examples/list_people.py                                                    \
   examples/list_people.py                                                    \
   java/src/main/java/com/google/protobuf/AbstractMessage.java                \
   java/src/main/java/com/google/protobuf/AbstractMessage.java                \
+  java/src/main/java/com/google/protobuf/AbstractMessageLite.java            \
   java/src/main/java/com/google/protobuf/BlockingRpcChannel.java             \
   java/src/main/java/com/google/protobuf/BlockingRpcChannel.java             \
   java/src/main/java/com/google/protobuf/BlockingService.java                \
   java/src/main/java/com/google/protobuf/BlockingService.java                \
   java/src/main/java/com/google/protobuf/ByteString.java                     \
   java/src/main/java/com/google/protobuf/ByteString.java                     \
@@ -70,10 +71,14 @@ EXTRA_DIST =                                                                 \
   java/src/main/java/com/google/protobuf/Descriptors.java                    \
   java/src/main/java/com/google/protobuf/Descriptors.java                    \
   java/src/main/java/com/google/protobuf/DynamicMessage.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/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/FieldSet.java                       \
   java/src/main/java/com/google/protobuf/GeneratedMessage.java               \
   java/src/main/java/com/google/protobuf/GeneratedMessage.java               \
+  java/src/main/java/com/google/protobuf/GeneratedMessageLite.java           \
+  java/src/main/java/com/google/protobuf/Internal.java                       \
   java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
   java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
   java/src/main/java/com/google/protobuf/Message.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/ProtocolMessageEnum.java            \
   java/src/main/java/com/google/protobuf/RpcCallback.java                    \
   java/src/main/java/com/google/protobuf/RpcCallback.java                    \
   java/src/main/java/com/google/protobuf/RpcChannel.java                     \
   java/src/main/java/com/google/protobuf/RpcChannel.java                     \
@@ -91,6 +96,7 @@ EXTRA_DIST =                                                                 \
   java/src/test/java/com/google/protobuf/DescriptorsTest.java                \
   java/src/test/java/com/google/protobuf/DescriptorsTest.java                \
   java/src/test/java/com/google/protobuf/DynamicMessageTest.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/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/MessageTest.java                    \
   java/src/test/java/com/google/protobuf/ServiceTest.java                    \
   java/src/test/java/com/google/protobuf/ServiceTest.java                    \
   java/src/test/java/com/google/protobuf/TestUtil.java                       \
   java/src/test/java/com/google/protobuf/TestUtil.java                       \
@@ -110,6 +116,7 @@ EXTRA_DIST =                                                                 \
   python/google/protobuf/internal/input_stream.py                            \
   python/google/protobuf/internal/input_stream.py                            \
   python/google/protobuf/internal/input_stream_test.py                       \
   python/google/protobuf/internal/input_stream_test.py                       \
   python/google/protobuf/internal/message_listener.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_extensions.proto                      \
   python/google/protobuf/internal/more_messages.proto                        \
   python/google/protobuf/internal/more_messages.proto                        \
   python/google/protobuf/internal/output_stream.py                           \
   python/google/protobuf/internal/output_stream.py                           \

+ 5 - 1
generate_descriptor_proto.sh

@@ -5,6 +5,10 @@
 # itself, they cannot be generated automatically by a make rule.  "make check"
 # 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
 # will fail if these files do not match what the protocol compiler would
 # generate.
 # 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
 if test ! -e src/google/protobuf/stubs/common.h; then
   cat >&2 << __EOF__
   cat >&2 << __EOF__
@@ -23,5 +27,5 @@ __EOF__
 fi
 fi
 
 
 cd src
 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 ..
 cd ..

+ 3 - 0
java/pom.xml

@@ -124,6 +124,9 @@
                     value="../src/google/protobuf/unittest_optimize_for.proto" />
                     value="../src/google/protobuf/unittest_optimize_for.proto" />
                   <arg
                   <arg
                     value="../src/google/protobuf/unittest_custom_options.proto" />
                     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>
                 </exec>
               </tasks>
               </tasks>
               <testSourceRoot>target/generated-test-sources</testSourceRoot>
               <testSourceRoot>target/generated-test-sources</testSourceRoot>

+ 457 - 224
java/src/main/java/com/google/protobuf/AbstractMessage.java

@@ -30,12 +30,12 @@
 
 
 package com.google.protobuf;
 package com.google.protobuf;
 
 
+import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 
 
-import java.io.FilterInputStream;
 import java.io.InputStream;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.IOException;
-import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 
 
@@ -45,11 +45,12 @@ import java.util.Map;
  *
  *
  * @author kenton@google.com Kenton Varda
  * @author kenton@google.com Kenton Varda
  */
  */
-public abstract class AbstractMessage implements Message {
+public abstract class AbstractMessage extends AbstractMessageLite
+                                      implements Message {
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
   public boolean isInitialized() {
   public boolean isInitialized() {
     // Check that all required fields are present.
     // Check that all required fields are present.
-    for (FieldDescriptor field : getDescriptorForType().getFields()) {
+    for (final FieldDescriptor field : getDescriptorForType().getFields()) {
       if (field.isRequired()) {
       if (field.isRequired()) {
         if (!hasField(field)) {
         if (!hasField(field)) {
           return false;
           return false;
@@ -58,11 +59,12 @@ public abstract class AbstractMessage implements Message {
     }
     }
 
 
     // Check that embedded messages are initialized.
     // 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.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         if (field.isRepeated()) {
         if (field.isRepeated()) {
-          for (Message element : (List<Message>) entry.getValue()) {
+          for (final Message element : (List<Message>) entry.getValue()) {
             if (!element.isInitialized()) {
             if (!element.isInitialized()) {
               return false;
               return false;
             }
             }
@@ -83,117 +85,59 @@ public abstract class AbstractMessage implements Message {
     return TextFormat.printToString(this);
     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()) {
-
-          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);
-          }
-        }
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    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()) {
+        output.writeMessageSetExtension(field.getNumber(), (Message) value);
       } else {
       } 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);
       unknownFields.writeAsMessageSetTo(output);
     } else {
     } else {
       unknownFields.writeTo(output);
       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;
   private int memoizedSize = -1;
 
 
   public int getSerializedSize() {
   public int getSerializedSize() {
     int size = memoizedSize;
     int size = memoizedSize;
-    if (size != -1) return size;
+    if (size != -1) {
+      return size;
+    }
 
 
     size = 0;
     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 {
       } 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();
       size += unknownFields.getSerializedSizeAsMessageSet();
     } else {
     } else {
       size += unknownFields.getSerializedSize();
       size += unknownFields.getSerializedSize();
@@ -204,14 +148,14 @@ public abstract class AbstractMessage implements Message {
   }
   }
 
 
   @Override
   @Override
-  public boolean equals(Object other) {
+  public boolean equals(final Object other) {
     if (other == this) {
     if (other == this) {
       return true;
       return true;
     }
     }
     if (!(other instanceof Message)) {
     if (!(other instanceof Message)) {
       return false;
       return false;
     }
     }
-    Message otherMessage = (Message) other;
+    final Message otherMessage = (Message) other;
     if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
     if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
       return false;
       return false;
     }
     }
@@ -237,20 +181,21 @@ public abstract class AbstractMessage implements Message {
    */
    */
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
   public static abstract class Builder<BuilderType extends Builder>
   public static abstract class Builder<BuilderType extends Builder>
+      extends AbstractMessageLite.Builder<BuilderType>
       implements Message.Builder {
       implements Message.Builder {
     // The compiler produces an error if this is not declared explicitly.
     // The compiler produces an error if this is not declared explicitly.
     @Override
     @Override
     public abstract BuilderType clone();
     public abstract BuilderType clone();
 
 
     public BuilderType clear() {
     public BuilderType clear() {
-      for (Map.Entry<FieldDescriptor, Object> entry :
+      for (final Map.Entry<FieldDescriptor, Object> entry :
            getAllFields().entrySet()) {
            getAllFields().entrySet()) {
         clearField(entry.getKey());
         clearField(entry.getKey());
       }
       }
       return (BuilderType) this;
       return (BuilderType) this;
     }
     }
 
 
-    public BuilderType mergeFrom(Message other) {
+    public BuilderType mergeFrom(final Message other) {
       if (other.getDescriptorForType() != getDescriptorForType()) {
       if (other.getDescriptorForType() != getDescriptorForType()) {
         throw new IllegalArgumentException(
         throw new IllegalArgumentException(
           "mergeFrom(Message) can only merge messages of the same type.");
           "mergeFrom(Message) can only merge messages of the same type.");
@@ -265,15 +210,15 @@ public abstract class AbstractMessage implements Message {
       // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
       // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
       //   which allows people to make secure deep copies of messages.
       //   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()) {
            other.getAllFields().entrySet()) {
-        FieldDescriptor field = entry.getKey();
+        final FieldDescriptor field = entry.getKey();
         if (field.isRepeated()) {
         if (field.isRepeated()) {
-          for (Object element : (List)entry.getValue()) {
+          for (final Object element : (List)entry.getValue()) {
             addRepeatedField(field, element);
             addRepeatedField(field, element);
           }
           }
         } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-          Message existingValue = (Message)getField(field);
+          final Message existingValue = (Message)getField(field);
           if (existingValue == existingValue.getDefaultInstanceForType()) {
           if (existingValue == existingValue.getDefaultInstanceForType()) {
             setField(field, entry.getValue());
             setField(field, entry.getValue());
           } else {
           } else {
@@ -288,24 +233,288 @@ public abstract class AbstractMessage implements Message {
         }
         }
       }
       }
 
 
+      mergeUnknownFields(other.getUnknownFields());
+
       return (BuilderType) this;
       return (BuilderType) this;
     }
     }
 
 
-    public BuilderType mergeFrom(CodedInputStream input) throws IOException {
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input)
+                                 throws IOException {
       return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
       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());
         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());
       setUnknownFields(unknownFields.build());
       return (BuilderType) this;
       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(
       setUnknownFields(
         UnknownFieldSet.newBuilder(getUnknownFields())
         UnknownFieldSet.newBuilder(getUnknownFields())
                        .mergeFrom(unknownFields)
                        .mergeFrom(unknownFields)
@@ -313,145 +522,169 @@ public abstract class AbstractMessage implements Message {
       return (BuilderType) this;
       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());
       }
       }
+      if (index != -1) {
+        result.append('[')
+              .append(index)
+              .append(']');
+      }
+      result.append('.');
+      return result.toString();
     }
     }
 
 
-    public BuilderType mergeFrom(byte[] data)
+    // ===============================================================
+    // 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 {
         throws InvalidProtocolBufferException {
-      return mergeFrom(data, 0, data.length);
+      return super.mergeFrom(data);
     }
     }
 
 
-    public BuilderType mergeFrom(byte[] data, int off, int len)
+    @Override
+    public BuilderType mergeFrom(
+        final ByteString data,
+        final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
         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);
-      }
+      return super.mergeFrom(data, extensionRegistry);
     }
     }
 
 
-    public BuilderType mergeFrom(
-        byte[] data,
-        ExtensionRegistry extensionRegistry)
+    @Override
+    public BuilderType mergeFrom(final byte[] data)
         throws InvalidProtocolBufferException {
         throws InvalidProtocolBufferException {
-      return mergeFrom(data, 0, data.length, extensionRegistry);
+      return super.mergeFrom(data);
     }
     }
 
 
+    @Override
     public BuilderType mergeFrom(
     public BuilderType mergeFrom(
-        byte[] data, int off, int len,
-        ExtensionRegistry extensionRegistry)
+        final byte[] data, final int off, final int len)
         throws InvalidProtocolBufferException {
         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 BuilderType mergeFrom(final InputStream input)
+        throws IOException {
+      return super.mergeFrom(input);
+    }
 
 
-        @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 BuilderType mergeFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return super.mergeFrom(input, extensionRegistry);
+    }
 
 
-        @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);
+    @Override
+    public BuilderType mergeDelimitedFrom(final InputStream input)
+        throws IOException {
+      return super.mergeDelimitedFrom(input);
     }
     }
 
 
-    public BuilderType mergeDelimitedFrom(InputStream input)
+    @Override
+    public BuilderType mergeDelimitedFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
         throws IOException {
         throws IOException {
-      return mergeDelimitedFrom(input, ExtensionRegistry.getEmptyRegistry());
+      return super.mergeDelimitedFrom(input, extensionRegistry);
     }
     }
+
   }
   }
 }
 }

+ 321 - 0
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);
+        }
+      }
+    }
+  }
+}

+ 39 - 37
java/src/main/java/com/google/protobuf/ByteString.java

@@ -46,7 +46,7 @@ import java.nio.ByteBuffer;
 public final class ByteString {
 public final class ByteString {
   private final byte[] bytes;
   private final byte[] bytes;
 
 
-  private ByteString(byte[] bytes) {
+  private ByteString(final byte[] bytes) {
     this.bytes = bytes;
     this.bytes = bytes;
   }
   }
 
 
@@ -55,7 +55,7 @@ public final class ByteString {
    *
    *
    * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
    * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
    */
    */
-  public byte byteAt(int index) {
+  public byte byteAt(final int index) {
     return bytes[index];
     return bytes[index];
   }
   }
 
 
@@ -63,14 +63,14 @@ public final class ByteString {
    * Gets the number of bytes.
    * Gets the number of bytes.
    */
    */
   public int size() {
   public int size() {
-    return this.bytes.length;
+    return bytes.length;
   }
   }
 
 
   /**
   /**
    * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
    * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
    */
    */
   public boolean isEmpty() {
   public boolean isEmpty() {
-    return this.bytes.length == 0;
+    return bytes.length == 0;
   }
   }
 
 
   // =================================================================
   // =================================================================
@@ -84,8 +84,9 @@ public final class ByteString {
   /**
   /**
    * Copies the given bytes into a {@code ByteString}.
    * 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);
     System.arraycopy(bytes, offset, copy, 0, size);
     return new ByteString(copy);
     return new ByteString(copy);
   }
   }
@@ -93,7 +94,7 @@ public final class ByteString {
   /**
   /**
    * Copies the given bytes into a {@code ByteString}.
    * 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);
     return copyFrom(bytes, 0, bytes.length);
   }
   }
 
 
@@ -101,7 +102,7 @@ public final class ByteString {
    * Encodes {@code text} into a sequence of bytes using the named charset
    * Encodes {@code text} into a sequence of bytes using the named charset
    * and returns the result as a {@code ByteString}.
    * 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 {
       throws UnsupportedEncodingException {
     return new ByteString(text.getBytes(charsetName));
     return new ByteString(text.getBytes(charsetName));
   }
   }
@@ -110,7 +111,7 @@ public final class ByteString {
    * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
    * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
    * result as a {@code ByteString}.
    * result as a {@code ByteString}.
    */
    */
-  public static ByteString copyFromUtf8(String text) {
+  public static ByteString copyFromUtf8(final String text) {
     try {
     try {
       return new ByteString(text.getBytes("UTF-8"));
       return new ByteString(text.getBytes("UTF-8"));
     } catch (UnsupportedEncodingException e) {
     } catch (UnsupportedEncodingException e) {
@@ -127,7 +128,7 @@ public final class ByteString {
    * @param target buffer to copy into
    * @param target buffer to copy into
    * @param offset in the target buffer
    * @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);
     System.arraycopy(bytes, 0, target, offset, bytes.length);
   }
   }
 
 
@@ -139,8 +140,9 @@ public final class ByteString {
    * @param targetOffset offset within the target buffer
    * @param targetOffset offset within the target buffer
    * @param size number of bytes to copy
    * @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);
     System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
   }
   }
 
 
@@ -148,9 +150,9 @@ public final class ByteString {
    * Copies bytes to a {@code byte[]}.
    * Copies bytes to a {@code byte[]}.
    */
    */
   public byte[] toByteArray() {
   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;
     return copy;
   }
   }
 
 
@@ -159,7 +161,7 @@ public final class ByteString {
    * same backing byte array.
    * same backing byte array.
    */
    */
   public ByteBuffer asReadOnlyByteBuffer() {
   public ByteBuffer asReadOnlyByteBuffer() {
-    ByteBuffer byteBuffer = ByteBuffer.wrap(this.bytes);
+    final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
     return byteBuffer.asReadOnlyBuffer();
     return byteBuffer.asReadOnlyBuffer();
   }
   }
 
 
@@ -167,9 +169,9 @@ public final class ByteString {
    * Constructs a new {@code String} by decoding the bytes using the
    * Constructs a new {@code String} by decoding the bytes using the
    * specified charset.
    * specified charset.
    */
    */
-  public String toString(String charsetName)
+  public String toString(final String charsetName)
       throws UnsupportedEncodingException {
       throws UnsupportedEncodingException {
-    return new String(this.bytes, charsetName);
+    return new String(bytes, charsetName);
   }
   }
 
 
   /**
   /**
@@ -177,7 +179,7 @@ public final class ByteString {
    */
    */
   public String toStringUtf8() {
   public String toStringUtf8() {
     try {
     try {
-      return new String(this.bytes, "UTF-8");
+      return new String(bytes, "UTF-8");
     } catch (UnsupportedEncodingException e) {
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported?", e);
       throw new RuntimeException("UTF-8 not supported?", e);
     }
     }
@@ -187,7 +189,7 @@ public final class ByteString {
   // equals() and hashCode()
   // equals() and hashCode()
 
 
   @Override
   @Override
-  public boolean equals(Object o) {
+  public boolean equals(final Object o) {
     if (o == this) {
     if (o == this) {
       return true;
       return true;
     }
     }
@@ -196,16 +198,16 @@ public final class ByteString {
       return false;
       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) {
     if (size != other.bytes.length) {
       return false;
       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++) {
     for (int i = 0; i < size; i++) {
-      if (bytes[i] != otherBytes[i]) {
+      if (thisBytes[i] != otherBytes[i]) {
         return false;
         return false;
       }
       }
     }
     }
@@ -213,25 +215,25 @@ public final class ByteString {
     return true;
     return true;
   }
   }
 
 
-  volatile int hash = 0;
+  private volatile int hash = 0;
 
 
   @Override
   @Override
   public int hashCode() {
   public int hashCode() {
-    int h = this.hash;
+    int h = hash;
 
 
     if (h == 0) {
     if (h == 0) {
-      byte[] bytes = this.bytes;
-      int size = this.bytes.length;
+      final byte[] thisBytes = bytes;
+      final int size = bytes.length;
 
 
       h = size;
       h = size;
       for (int i = 0; i < size; i++) {
       for (int i = 0; i < size; i++) {
-        h = h * 31 + bytes[i];
+        h = h * 31 + thisBytes[i];
       }
       }
       if (h == 0) {
       if (h == 0) {
         h = 1;
         h = 1;
       }
       }
 
 
-      this.hash = h;
+      hash = h;
     }
     }
 
 
     return h;
     return h;
@@ -264,7 +266,7 @@ public final class ByteString {
   /**
   /**
    * Creates a new {@link Output} with the given initial capacity.
    * 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));
     return new Output(new ByteArrayOutputStream(initialCapacity));
   }
   }
 
 
@@ -285,7 +287,7 @@ public final class ByteString {
     /**
     /**
      * Constructs a new output with the given initial capacity.
      * Constructs a new output with the given initial capacity.
      */
      */
-    private Output(ByteArrayOutputStream bout) {
+    private Output(final ByteArrayOutputStream bout) {
       super(bout);
       super(bout);
       this.bout = bout;
       this.bout = bout;
     }
     }
@@ -294,14 +296,14 @@ public final class ByteString {
      * Creates a {@code ByteString} instance from this {@code Output}.
      * Creates a {@code ByteString} instance from this {@code Output}.
      */
      */
     public ByteString toByteString() {
     public ByteString toByteString() {
-      byte[] byteArray = bout.toByteArray();
+      final byte[] byteArray = bout.toByteArray();
       return new ByteString(byteArray);
       return new ByteString(byteArray);
     }
     }
   }
   }
 
 
   /**
   /**
    * Constructs a new ByteString builder, which allows you to efficiently
    * 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
    * Using this is much more efficient than calling {@code newOutput()} and
    * wrapping that in a {@code CodedOutputStream}.
    * wrapping that in a {@code CodedOutputStream}.
    *
    *
@@ -312,7 +314,7 @@ public final class ByteString {
    * @param size The target byte size of the {@code ByteString}.  You must
    * @param size The target byte size of the {@code ByteString}.  You must
    *             write exactly this many bytes before building the result.
    *             write exactly this many bytes before building the result.
    */
    */
-  static CodedBuilder newCodedBuilder(int size) {
+  static CodedBuilder newCodedBuilder(final int size) {
     return new CodedBuilder(size);
     return new CodedBuilder(size);
   }
   }
 
 
@@ -321,7 +323,7 @@ public final class ByteString {
     private final CodedOutputStream output;
     private final CodedOutputStream output;
     private final byte[] buffer;
     private final byte[] buffer;
 
 
-    private CodedBuilder(int size) {
+    private CodedBuilder(final int size) {
       buffer = new byte[size];
       buffer = new byte[size];
       output = CodedOutputStream.newInstance(buffer);
       output = CodedOutputStream.newInstance(buffer);
     }
     }

+ 95 - 129
java/src/main/java/com/google/protobuf/CodedInputStream.java

@@ -51,21 +51,22 @@ public final class CodedInputStream {
   /**
   /**
    * Create a new CodedInputStream wrapping the given InputStream.
    * 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);
     return new CodedInputStream(input);
   }
   }
 
 
   /**
   /**
    * Create a new CodedInputStream wrapping the given byte array.
    * 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);
     return newInstance(buf, 0, buf.length);
   }
   }
 
 
   /**
   /**
    * Create a new CodedInputStream wrapping the given byte array slice.
    * 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);
     return new CodedInputStream(buf, off, len);
   }
   }
 
 
@@ -98,7 +99,8 @@ public final class CodedInputStream {
    * @throws InvalidProtocolBufferException {@code value} does not match the
    * @throws InvalidProtocolBufferException {@code value} does not match the
    *                                        last tag.
    *                                        last tag.
    */
    */
-  public void checkLastTagWas(int value) throws InvalidProtocolBufferException {
+  public void checkLastTagWas(final int value)
+                              throws InvalidProtocolBufferException {
     if (lastTag != value) {
     if (lastTag != value) {
       throw InvalidProtocolBufferException.invalidEndTag();
       throw InvalidProtocolBufferException.invalidEndTag();
     }
     }
@@ -110,7 +112,7 @@ public final class CodedInputStream {
    * @return {@code false} if the tag is an endgroup tag, in which case
    * @return {@code false} if the tag is an endgroup tag, in which case
    *         nothing is skipped.  Otherwise, returns {@code true}.
    *         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)) {
     switch (WireFormat.getTagWireType(tag)) {
       case WireFormat.WIRETYPE_VARINT:
       case WireFormat.WIRETYPE_VARINT:
         readInt32();
         readInt32();
@@ -143,8 +145,10 @@ public final class CodedInputStream {
    */
    */
   public void skipMessage() throws IOException {
   public void skipMessage() throws IOException {
     while (true) {
     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 @@ public final class CodedInputStream {
 
 
   /** Read a {@code string} field value from the stream. */
   /** Read a {@code string} field value from the stream. */
   public String readString() throws IOException {
   public String readString() throws IOException {
-    int size = readRawVarint32();
+    final int size = readRawVarint32();
     if (size <= (bufferSize - bufferPos) && size > 0) {
     if (size <= (bufferSize - bufferPos) && size > 0) {
       // Fast path:  We already have the bytes in a contiguous buffer, so
       // Fast path:  We already have the bytes in a contiguous buffer, so
       //   just copy directly from it.
       //   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;
       bufferPos += size;
       return result;
       return result;
     } else {
     } else {
@@ -206,8 +210,9 @@ public final class CodedInputStream {
   }
   }
 
 
   /** Read a {@code group} field value from the stream. */
   /** 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 {
       throws IOException {
     if (recursionDepth >= recursionLimit) {
     if (recursionDepth >= recursionLimit) {
       throw InvalidProtocolBufferException.recursionLimitExceeded();
       throw InvalidProtocolBufferException.recursionLimitExceeded();
@@ -222,28 +227,31 @@ public final class CodedInputStream {
   /**
   /**
    * Reads a {@code group} field value from the stream and merges it into the
    * Reads a {@code group} field value from the stream and merges it into the
    * given {@link UnknownFieldSet}.
    * 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 {
       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. */
   /** 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 {
       throws IOException {
-    int length = readRawVarint32();
+    final int length = readRawVarint32();
     if (recursionDepth >= recursionLimit) {
     if (recursionDepth >= recursionLimit) {
       throw InvalidProtocolBufferException.recursionLimitExceeded();
       throw InvalidProtocolBufferException.recursionLimitExceeded();
     }
     }
-    int oldLimit = pushLimit(length);
+    final int oldLimit = pushLimit(length);
     ++recursionDepth;
     ++recursionDepth;
     builder.mergeFrom(this, extensionRegistry);
     builder.mergeFrom(this, extensionRegistry);
     checkLastTagWas(0);
     checkLastTagWas(0);
@@ -253,11 +261,11 @@ public final class CodedInputStream {
 
 
   /** Read a {@code bytes} field value from the stream. */
   /** Read a {@code bytes} field value from the stream. */
   public ByteString readBytes() throws IOException {
   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
       // Fast path:  We already have the bytes in a contiguous buffer, so
       //   just copy directly from it.
       //   just copy directly from it.
-      ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
+      final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
       bufferPos += size;
       bufferPos += size;
       return result;
       return result;
     } else {
     } else {
@@ -299,52 +307,6 @@ public final class CodedInputStream {
     return decodeZigZag64(readRawVarint64());
     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 @@ public final class CodedInputStream {
           if (tmp < 0) {
           if (tmp < 0) {
             // Discard upper 32 bits.
             // Discard upper 32 bits.
             for (int i = 0; i < 5; i++) {
             for (int i = 0; i < 5; i++) {
-              if (readRawByte() >= 0) return result;
+              if (readRawByte() >= 0) {
+                return result;
+              }
             }
             }
             throw InvalidProtocolBufferException.malformedVarint();
             throw InvalidProtocolBufferException.malformedVarint();
           }
           }
@@ -390,11 +354,11 @@ public final class CodedInputStream {
    * then you would probably end up reading past the end of the varint since
    * then you would probably end up reading past the end of the varint since
    * CodedInputStream buffers its input.
    * CodedInputStream buffers its input.
    */
    */
-  static int readRawVarint32(InputStream input) throws IOException {
+  static int readRawVarint32(final InputStream input) throws IOException {
     int result = 0;
     int result = 0;
     int offset = 0;
     int offset = 0;
     for (; offset < 32; offset += 7) {
     for (; offset < 32; offset += 7) {
-      int b = input.read();
+      final int b = input.read();
       if (b == -1) {
       if (b == -1) {
         throw InvalidProtocolBufferException.truncatedMessage();
         throw InvalidProtocolBufferException.truncatedMessage();
       }
       }
@@ -405,7 +369,7 @@ public final class CodedInputStream {
     }
     }
     // Keep reading up to 64 bits.
     // Keep reading up to 64 bits.
     for (; offset < 64; offset += 7) {
     for (; offset < 64; offset += 7) {
-      int b = input.read();
+      final int b = input.read();
       if (b == -1) {
       if (b == -1) {
         throw InvalidProtocolBufferException.truncatedMessage();
         throw InvalidProtocolBufferException.truncatedMessage();
       }
       }
@@ -421,9 +385,11 @@ public final class CodedInputStream {
     int shift = 0;
     int shift = 0;
     long result = 0;
     long result = 0;
     while (shift < 64) {
     while (shift < 64) {
-      byte b = readRawByte();
+      final byte b = readRawByte();
       result |= (long)(b & 0x7F) << shift;
       result |= (long)(b & 0x7F) << shift;
-      if ((b & 0x80) == 0) return result;
+      if ((b & 0x80) == 0) {
+        return result;
+      }
       shift += 7;
       shift += 7;
     }
     }
     throw InvalidProtocolBufferException.malformedVarint();
     throw InvalidProtocolBufferException.malformedVarint();
@@ -431,10 +397,10 @@ public final class CodedInputStream {
 
 
   /** Read a 32-bit little-endian integer from the stream. */
   /** Read a 32-bit little-endian integer from the stream. */
   public int readRawLittleEndian32() throws IOException {
   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)      ) |
     return (((int)b1 & 0xff)      ) |
            (((int)b2 & 0xff) <<  8) |
            (((int)b2 & 0xff) <<  8) |
            (((int)b3 & 0xff) << 16) |
            (((int)b3 & 0xff) << 16) |
@@ -443,14 +409,14 @@ public final class CodedInputStream {
 
 
   /** Read a 64-bit little-endian integer from the stream. */
   /** Read a 64-bit little-endian integer from the stream. */
   public long readRawLittleEndian64() throws IOException {
   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)      ) |
     return (((long)b1 & 0xff)      ) |
            (((long)b2 & 0xff) <<  8) |
            (((long)b2 & 0xff) <<  8) |
            (((long)b3 & 0xff) << 16) |
            (((long)b3 & 0xff) << 16) |
@@ -471,7 +437,7 @@ public final class CodedInputStream {
    *          Java has no explicit unsigned support.
    *          Java has no explicit unsigned support.
    * @return A signed 32-bit integer.
    * @return A signed 32-bit integer.
    */
    */
-  public static int decodeZigZag32(int n) {
+  public static int decodeZigZag32(final int n) {
     return (n >>> 1) ^ -(n & 1);
     return (n >>> 1) ^ -(n & 1);
   }
   }
 
 
@@ -485,31 +451,31 @@ public final class CodedInputStream {
    *          Java has no explicit unsigned support.
    *          Java has no explicit unsigned support.
    * @return A signed 64-bit integer.
    * @return A signed 64-bit integer.
    */
    */
-  public static long decodeZigZag64(long n) {
+  public static long decodeZigZag64(final long n) {
     return (n >>> 1) ^ -(n & 1);
     return (n >>> 1) ^ -(n & 1);
   }
   }
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
 
 
-  private byte[] buffer;
+  private final byte[] buffer;
   private int bufferSize;
   private int bufferSize;
-  private int bufferSizeAfterLimit = 0;
+  private int bufferSizeAfterLimit;
   private int bufferPos;
   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
    * The total number of bytes read before the current buffer.  The total
    * bytes read up to the current position can be computed as
    * bytes read up to the current position can be computed as
    * {@code totalBytesRetired + bufferPos}.
    * {@code totalBytesRetired + bufferPos}.
    */
    */
-  private int totalBytesRetired = 0;
+  private int totalBytesRetired;
 
 
   /** The absolute position of the end of the current message. */
   /** The absolute position of the end of the current message. */
   private int currentLimit = Integer.MAX_VALUE;
   private int currentLimit = Integer.MAX_VALUE;
 
 
   /** See setRecursionLimit() */
   /** See setRecursionLimit() */
-  private int recursionDepth = 0;
+  private int recursionDepth;
   private int recursionLimit = DEFAULT_RECURSION_LIMIT;
   private int recursionLimit = DEFAULT_RECURSION_LIMIT;
 
 
   /** See setSizeLimit() */
   /** See setSizeLimit() */
@@ -519,17 +485,17 @@ public final class CodedInputStream {
   private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
   private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
   private static final int BUFFER_SIZE = 4096;
   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.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;
     this.input = input;
   }
   }
 
 
@@ -540,12 +506,12 @@ public final class CodedInputStream {
    *
    *
    * @return the old limit.
    * @return the old limit.
    */
    */
-  public int setRecursionLimit(int limit) {
+  public int setRecursionLimit(final int limit) {
     if (limit < 0) {
     if (limit < 0) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
         "Recursion limit cannot be negative: " + limit);
         "Recursion limit cannot be negative: " + limit);
     }
     }
-    int oldLimit = recursionLimit;
+    final int oldLimit = recursionLimit;
     recursionLimit = limit;
     recursionLimit = limit;
     return oldLimit;
     return oldLimit;
   }
   }
@@ -566,12 +532,12 @@ public final class CodedInputStream {
    *
    *
    * @return the old limit.
    * @return the old limit.
    */
    */
-  public int setSizeLimit(int limit) {
+  public int setSizeLimit(final int limit) {
     if (limit < 0) {
     if (limit < 0) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
         "Size limit cannot be negative: " + limit);
         "Size limit cannot be negative: " + limit);
     }
     }
-    int oldLimit = sizeLimit;
+    final int oldLimit = sizeLimit;
     sizeLimit = limit;
     sizeLimit = limit;
     return oldLimit;
     return oldLimit;
   }
   }
@@ -594,7 +560,7 @@ public final class CodedInputStream {
       throw InvalidProtocolBufferException.negativeSize();
       throw InvalidProtocolBufferException.negativeSize();
     }
     }
     byteLimit += totalBytesRetired + bufferPos;
     byteLimit += totalBytesRetired + bufferPos;
-    int oldLimit = currentLimit;
+    final int oldLimit = currentLimit;
     if (byteLimit > oldLimit) {
     if (byteLimit > oldLimit) {
       throw InvalidProtocolBufferException.truncatedMessage();
       throw InvalidProtocolBufferException.truncatedMessage();
     }
     }
@@ -607,7 +573,7 @@ public final class CodedInputStream {
 
 
   private void recomputeBufferSizeAfterLimit() {
   private void recomputeBufferSizeAfterLimit() {
     bufferSize += bufferSizeAfterLimit;
     bufferSize += bufferSizeAfterLimit;
-    int bufferEnd = totalBytesRetired + bufferSize;
+    final int bufferEnd = totalBytesRetired + bufferSize;
     if (bufferEnd > currentLimit) {
     if (bufferEnd > currentLimit) {
       // Limit is in current buffer.
       // Limit is in current buffer.
       bufferSizeAfterLimit = bufferEnd - currentLimit;
       bufferSizeAfterLimit = bufferEnd - currentLimit;
@@ -622,7 +588,7 @@ public final class CodedInputStream {
    *
    *
    * @param oldLimit The old limit, as returned by {@code pushLimit}.
    * @param oldLimit The old limit, as returned by {@code pushLimit}.
    */
    */
-  public void popLimit(int oldLimit) {
+  public void popLimit(final int oldLimit) {
     currentLimit = oldLimit;
     currentLimit = oldLimit;
     recomputeBufferSizeAfterLimit();
     recomputeBufferSizeAfterLimit();
   }
   }
@@ -636,7 +602,7 @@ public final class CodedInputStream {
       return -1;
       return -1;
     }
     }
 
 
-    int currentAbsolutePosition = totalBytesRetired + bufferPos;
+    final int currentAbsolutePosition = totalBytesRetired + bufferPos;
     return currentLimit - currentAbsolutePosition;
     return currentLimit - currentAbsolutePosition;
   }
   }
 
 
@@ -656,7 +622,7 @@ public final class CodedInputStream {
    * or it will throw an exception.  If {@code mustSucceed} is false,
    * or it will throw an exception.  If {@code mustSucceed} is false,
    * refillBuffer() returns false if no more bytes were available.
    * 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) {
     if (bufferPos < bufferSize) {
       throw new IllegalStateException(
       throw new IllegalStateException(
         "refillBuffer() called when buffer wasn't empty.");
         "refillBuffer() called when buffer wasn't empty.");
@@ -689,7 +655,7 @@ public final class CodedInputStream {
       }
       }
     } else {
     } else {
       recomputeBufferSizeAfterLimit();
       recomputeBufferSizeAfterLimit();
-      int totalBytesRead =
+      final int totalBytesRead =
         totalBytesRetired + bufferSize + bufferSizeAfterLimit;
         totalBytesRetired + bufferSize + bufferSizeAfterLimit;
       if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
       if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
         throw InvalidProtocolBufferException.sizeLimitExceeded();
         throw InvalidProtocolBufferException.sizeLimitExceeded();
@@ -717,7 +683,7 @@ public final class CodedInputStream {
    * @throws InvalidProtocolBufferException The end of the stream or the current
    * @throws InvalidProtocolBufferException The end of the stream or the current
    *                                        limit was reached.
    *                                        limit was reached.
    */
    */
-  public byte[] readRawBytes(int size) throws IOException {
+  public byte[] readRawBytes(final int size) throws IOException {
     if (size < 0) {
     if (size < 0) {
       throw InvalidProtocolBufferException.negativeSize();
       throw InvalidProtocolBufferException.negativeSize();
     }
     }
@@ -731,7 +697,7 @@ public final class CodedInputStream {
 
 
     if (size <= bufferSize - bufferPos) {
     if (size <= bufferSize - bufferPos) {
       // We have all the bytes we need already.
       // 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);
       System.arraycopy(buffer, bufferPos, bytes, 0, size);
       bufferPos += size;
       bufferPos += size;
       return bytes;
       return bytes;
@@ -740,7 +706,7 @@ public final class CodedInputStream {
       // of bytes.  We can safely allocate the resulting array ahead of time.
       // of bytes.  We can safely allocate the resulting array ahead of time.
 
 
       // First copy what we have.
       // First copy what we have.
-      byte[] bytes = new byte[size];
+      final byte[] bytes = new byte[size];
       int pos = bufferSize - bufferPos;
       int pos = bufferSize - bufferPos;
       System.arraycopy(buffer, bufferPos, bytes, 0, pos);
       System.arraycopy(buffer, bufferPos, bytes, 0, pos);
       bufferPos = bufferSize;
       bufferPos = bufferSize;
@@ -772,8 +738,8 @@ public final class CodedInputStream {
 
 
       // Remember the buffer markers since we'll have to copy the bytes out of
       // Remember the buffer markers since we'll have to copy the bytes out of
       // it later.
       // it later.
-      int originalBufferPos = bufferPos;
-      int originalBufferSize = bufferSize;
+      final int originalBufferPos = bufferPos;
+      final int originalBufferSize = bufferSize;
 
 
       // Mark the current buffer consumed.
       // Mark the current buffer consumed.
       totalBytesRetired += bufferSize;
       totalBytesRetired += bufferSize;
@@ -782,13 +748,13 @@ public final class CodedInputStream {
 
 
       // Read all the rest of the bytes we need.
       // Read all the rest of the bytes we need.
       int sizeLeft = size - (originalBufferSize - originalBufferPos);
       int sizeLeft = size - (originalBufferSize - originalBufferPos);
-      List<byte[]> chunks = new ArrayList<byte[]>();
+      final List<byte[]> chunks = new ArrayList<byte[]>();
 
 
       while (sizeLeft > 0) {
       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;
         int pos = 0;
         while (pos < chunk.length) {
         while (pos < chunk.length) {
-          int n = (input == null) ? -1 :
+          final int n = (input == null) ? -1 :
             input.read(chunk, pos, chunk.length - pos);
             input.read(chunk, pos, chunk.length - pos);
           if (n == -1) {
           if (n == -1) {
             throw InvalidProtocolBufferException.truncatedMessage();
             throw InvalidProtocolBufferException.truncatedMessage();
@@ -801,14 +767,14 @@ public final class CodedInputStream {
       }
       }
 
 
       // OK, got everything.  Now concatenate it all into one buffer.
       // 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.
       // Start by copying the leftover bytes from this.buffer.
       int pos = originalBufferSize - originalBufferPos;
       int pos = originalBufferSize - originalBufferPos;
       System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
       System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
 
 
       // And now all the chunks.
       // And now all the chunks.
-      for (byte[] chunk : chunks) {
+      for (final byte[] chunk : chunks) {
         System.arraycopy(chunk, 0, bytes, pos, chunk.length);
         System.arraycopy(chunk, 0, bytes, pos, chunk.length);
         pos += chunk.length;
         pos += chunk.length;
       }
       }
@@ -824,7 +790,7 @@ public final class CodedInputStream {
    * @throws InvalidProtocolBufferException The end of the stream or the current
    * @throws InvalidProtocolBufferException The end of the stream or the current
    *                                        limit was reached.
    *                                        limit was reached.
    */
    */
-  public void skipRawBytes(int size) throws IOException {
+  public void skipRawBytes(final int size) throws IOException {
     if (size < 0) {
     if (size < 0) {
       throw InvalidProtocolBufferException.negativeSize();
       throw InvalidProtocolBufferException.negativeSize();
     }
     }
@@ -848,7 +814,7 @@ public final class CodedInputStream {
 
 
       // Then skip directly from the InputStream for the rest.
       // Then skip directly from the InputStream for the rest.
       while (pos < size) {
       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) {
         if (n <= 0) {
           throw InvalidProtocolBufferException.truncatedMessage();
           throw InvalidProtocolBufferException.truncatedMessage();
         }
         }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 174 - 240
java/src/main/java/com/google/protobuf/CodedOutputStream.java


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 246 - 184
java/src/main/java/com/google/protobuf/Descriptors.java


+ 52 - 29
java/src/main/java/com/google/protobuf/DynamicMessage.java

@@ -45,14 +45,14 @@ import java.util.Map;
  */
  */
 public final class DynamicMessage extends AbstractMessage {
 public final class DynamicMessage extends AbstractMessage {
   private final Descriptor type;
   private final Descriptor type;
-  private final FieldSet fields;
+  private final FieldSet<FieldDescriptor> fields;
   private final UnknownFieldSet unknownFields;
   private final UnknownFieldSet unknownFields;
   private int memoizedSize = -1;
   private int memoizedSize = -1;
 
 
   /**
   /**
    * Construct a {@code DynamicMessage} using the given {@code FieldSet}.
    * Construct a {@code DynamicMessage} using the given {@code FieldSet}.
    */
    */
-  private DynamicMessage(Descriptor type, FieldSet fields,
+  private DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
                          UnknownFieldSet unknownFields) {
                          UnknownFieldSet unknownFields) {
     this.type = type;
     this.type = type;
     this.fields = fields;
     this.fields = fields;
@@ -64,7 +64,7 @@ public final class DynamicMessage extends AbstractMessage {
    * given type.
    * given type.
    */
    */
   public static DynamicMessage getDefaultInstance(Descriptor type) {
   public static DynamicMessage getDefaultInstance(Descriptor type) {
-    return new DynamicMessage(type, FieldSet.emptySet(),
+    return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
                               UnknownFieldSet.getDefaultInstance());
                               UnknownFieldSet.getDefaultInstance());
   }
   }
 
 
@@ -160,7 +160,11 @@ public final class DynamicMessage extends AbstractMessage {
     verifyContainingType(field);
     verifyContainingType(field);
     Object result = fields.getField(field);
     Object result = fields.getField(field);
     if (result == null) {
     if (result == null) {
-      result = getDefaultInstance(field.getMessageType());
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        result = getDefaultInstance(field.getMessageType());
+      } else {
+        result = field.getDefaultValue();
+      }
     }
     }
     return result;
     return result;
   }
   }
@@ -179,15 +183,31 @@ public final class DynamicMessage extends AbstractMessage {
     return unknownFields;
     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() {
   public boolean isInitialized() {
-    return fields.isInitialized(type);
+    return isInitialized(type, fields);
   }
   }
 
 
   public void writeTo(CodedOutputStream output) throws IOException {
   public void writeTo(CodedOutputStream output) throws IOException {
-    fields.writeTo(output);
     if (type.getOptions().getMessageSetWireFormat()) {
     if (type.getOptions().getMessageSetWireFormat()) {
+      fields.writeMessageSetTo(output);
       unknownFields.writeAsMessageSetTo(output);
       unknownFields.writeAsMessageSetTo(output);
     } else {
     } else {
+      fields.writeTo(output);
       unknownFields.writeTo(output);
       unknownFields.writeTo(output);
     }
     }
   }
   }
@@ -196,10 +216,11 @@ public final class DynamicMessage extends AbstractMessage {
     int size = memoizedSize;
     int size = memoizedSize;
     if (size != -1) return size;
     if (size != -1) return size;
 
 
-    size = fields.getSerializedSize();
     if (type.getOptions().getMessageSetWireFormat()) {
     if (type.getOptions().getMessageSetWireFormat()) {
+      size = fields.getMessageSetSerializedSize();
       size += unknownFields.getSerializedSizeAsMessageSet();
       size += unknownFields.getSerializedSizeAsMessageSet();
     } else {
     } else {
+      size = fields.getSerializedSize();
       size += unknownFields.getSerializedSize();
       size += unknownFields.getSerializedSize();
     }
     }
 
 
@@ -230,7 +251,7 @@ public final class DynamicMessage extends AbstractMessage {
    */
    */
   public static final class Builder extends AbstractMessage.Builder<Builder> {
   public static final class Builder extends AbstractMessage.Builder<Builder> {
     private final Descriptor type;
     private final Descriptor type;
-    private FieldSet fields;
+    private FieldSet<FieldDescriptor> fields;
     private UnknownFieldSet unknownFields;
     private UnknownFieldSet unknownFields;
 
 
     /** Construct a {@code Builder} for the given type. */
     /** Construct a {@code Builder} for the given type. */
@@ -244,25 +265,33 @@ public final class DynamicMessage extends AbstractMessage {
     // Implementation of Message.Builder interface.
     // Implementation of Message.Builder interface.
 
 
     public Builder clear() {
     public Builder clear() {
+      if (fields == null) {
+        throw new IllegalStateException("Cannot call clear() after build().");
+      }
       fields.clear();
       fields.clear();
       return this;
       return this;
     }
     }
 
 
     public Builder mergeFrom(Message other) {
     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() {
     public DynamicMessage build() {
       // If fields == null, we'll throw an appropriate exception later.
       // If fields == null, we'll throw an appropriate exception later.
       if (fields != null && !isInitialized()) {
       if (fields != null && !isInitialized()) {
-        throw new UninitializedMessageException(
+        throw newUninitializedMessageException(
           new DynamicMessage(type, fields, unknownFields));
           new DynamicMessage(type, fields, unknownFields));
       }
       }
       return buildPartial();
       return buildPartial();
@@ -275,7 +304,7 @@ public final class DynamicMessage extends AbstractMessage {
      */
      */
     private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
     private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
       if (!isInitialized()) {
       if (!isInitialized()) {
-        throw new UninitializedMessageException(
+        throw newUninitializedMessageException(
             new DynamicMessage(type, fields, unknownFields))
             new DynamicMessage(type, fields, unknownFields))
           .asInvalidProtocolBufferException();
           .asInvalidProtocolBufferException();
       }
       }
@@ -302,17 +331,7 @@ public final class DynamicMessage extends AbstractMessage {
     }
     }
 
 
     public boolean isInitialized() {
     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() {
     public Descriptor getDescriptorForType() {
@@ -347,7 +366,11 @@ public final class DynamicMessage extends AbstractMessage {
       verifyContainingType(field);
       verifyContainingType(field);
       Object result = fields.getField(field);
       Object result = fields.getField(field);
       if (result == null) {
       if (result == null) {
-        result = getDefaultInstance(field.getMessageType());
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          result = getDefaultInstance(field.getMessageType());
+        } else {
+          result = field.getDefaultValue();
+        }
       }
       }
       return result;
       return result;
     }
     }

+ 45 - 35
java/src/main/java/com/google/protobuf/ExtensionRegistry.java

@@ -84,18 +84,16 @@ import java.util.Map;
  * would be slow.  Second, corrupt data would not be detected until first
  * 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
  * 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
  * 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
  * 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
  * @author kenton@google.com Kenton Varda
  */
  */
-public final class ExtensionRegistry {
+public final class ExtensionRegistry extends ExtensionRegistryLite {
   /** Construct a new, empty instance. */
   /** Construct a new, empty instance. */
   public static ExtensionRegistry newInstance() {
   public static ExtensionRegistry newInstance() {
-    return new ExtensionRegistry(
-      new HashMap<String, ExtensionInfo>(),
-      new HashMap<DescriptorIntPair, ExtensionInfo>());
+    return new ExtensionRegistry();
   }
   }
 
 
   /** Get the unmodifiable singleton empty instance. */
   /** Get the unmodifiable singleton empty instance. */
@@ -104,10 +102,9 @@ public final class ExtensionRegistry {
   }
   }
 
 
   /** Returns an unmodifiable view of the registry. */
   /** Returns an unmodifiable view of the registry. */
+  @Override
   public ExtensionRegistry getUnmodifiable() {
   public ExtensionRegistry getUnmodifiable() {
-    return new ExtensionRegistry(
-      Collections.unmodifiableMap(extensionsByName),
-      Collections.unmodifiableMap(extensionsByNumber));
+    return new ExtensionRegistry(this);
   }
   }
 
 
   /** A (Descriptor, Message) pair, returned by lookup methods. */
   /** A (Descriptor, Message) pair, returned by lookup methods. */
@@ -121,11 +118,12 @@ public final class ExtensionRegistry {
      */
      */
     public final Message defaultInstance;
     public final Message defaultInstance;
 
 
-    private ExtensionInfo(FieldDescriptor descriptor) {
+    private ExtensionInfo(final FieldDescriptor descriptor) {
       this.descriptor = 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.descriptor = descriptor;
       this.defaultInstance = defaultInstance;
       this.defaultInstance = defaultInstance;
     }
     }
@@ -139,7 +137,7 @@ public final class ExtensionRegistry {
    * @return Information about the extension if found, or {@code null}
    * @return Information about the extension if found, or {@code null}
    *         otherwise.
    *         otherwise.
    */
    */
-  public ExtensionInfo findExtensionByName(String fullName) {
+  public ExtensionInfo findExtensionByName(final String fullName) {
     return extensionsByName.get(fullName);
     return extensionsByName.get(fullName);
   }
   }
 
 
@@ -149,14 +147,14 @@ public final class ExtensionRegistry {
    * @return Information about the extension if found, or {@code null}
    * @return Information about the extension if found, or {@code null}
    *         otherwise.
    *         otherwise.
    */
    */
-  public ExtensionInfo findExtensionByNumber(Descriptor containingType,
-                                             int fieldNumber) {
+  public ExtensionInfo findExtensionByNumber(final Descriptor containingType,
+                                             final int fieldNumber) {
     return extensionsByNumber.get(
     return extensionsByNumber.get(
       new DescriptorIntPair(containingType, fieldNumber));
       new DescriptorIntPair(containingType, fieldNumber));
   }
   }
 
 
   /** Add an extension from a generated file to the registry. */
   /** 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() ==
     if (extension.getDescriptor().getJavaType() ==
         FieldDescriptor.JavaType.MESSAGE) {
         FieldDescriptor.JavaType.MESSAGE) {
       add(new ExtensionInfo(extension.getDescriptor(),
       add(new ExtensionInfo(extension.getDescriptor(),
@@ -167,7 +165,7 @@ public final class ExtensionRegistry {
   }
   }
 
 
   /** Add a non-message-type extension to the registry by descriptor. */
   /** 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) {
     if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
         "ExtensionRegistry.add() must be provided a default instance when " +
         "ExtensionRegistry.add() must be provided a default instance when " +
@@ -177,7 +175,7 @@ public final class ExtensionRegistry {
   }
   }
 
 
   /** Add a message-type extension to the registry by descriptor. */
   /** 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) {
     if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
         "ExtensionRegistry.add() provided a default instance for a " +
         "ExtensionRegistry.add() provided a default instance for a " +
@@ -189,22 +187,30 @@ public final class ExtensionRegistry {
   // =================================================================
   // =================================================================
   // Private stuff.
   // 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<String, ExtensionInfo> extensionsByName;
   private final Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
   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()) {
     if (!extension.descriptor.isExtension()) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
         "ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
         "ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
@@ -217,7 +223,7 @@ public final class ExtensionRegistry {
                             extension.descriptor.getNumber()),
                             extension.descriptor.getNumber()),
       extension);
       extension);
 
 
-    FieldDescriptor field = extension.descriptor;
+    final FieldDescriptor field = extension.descriptor;
     if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
     if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
         field.getType() == FieldDescriptor.Type.MESSAGE &&
         field.getType() == FieldDescriptor.Type.MESSAGE &&
         field.isOptional() &&
         field.isOptional() &&
@@ -231,20 +237,24 @@ public final class ExtensionRegistry {
 
 
   /** A (GenericDescriptor, int) pair, used as a map key. */
   /** A (GenericDescriptor, int) pair, used as a map key. */
   private static final class DescriptorIntPair {
   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.descriptor = descriptor;
       this.number = number;
       this.number = number;
     }
     }
 
 
+    @Override
     public int hashCode() {
     public int hashCode() {
       return descriptor.hashCode() * ((1 << 16) - 1) + number;
       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;
       return descriptor == other.descriptor && number == other.number;
     }
     }
   }
   }

+ 169 - 0
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;
+    }
+  }
+}

+ 449 - 461
java/src/main/java/com/google/protobuf/FieldSet.java

@@ -30,16 +30,13 @@
 
 
 package com.google.protobuf;
 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.ArrayList;
 import java.util.Collections;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Iterator;
 import java.util.TreeMap;
 import java.util.TreeMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.io.IOException;
 
 
 /**
 /**
  * A class which represents an arbitrary set of fields of some message type.
  * A class which represents an arbitrary set of fields of some message type.
@@ -49,43 +46,70 @@ import java.util.Map;
  *
  *
  * @author kenton@google.com Kenton Varda
  * @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. */
   /** Construct a new FieldSet. */
   private FieldSet() {
   private FieldSet() {
     // Use a TreeMap because fields need to be in canonical order when
     // Use a TreeMap because fields need to be in canonical order when
     // serializing.
     // 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. */
   /** 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. */
   /** Get an immutable empty FieldSet. */
-  public static FieldSet emptySet() {
+  @SuppressWarnings("unchecked")
+  public static <T extends FieldSet.FieldDescriptorLite<T>>
+      FieldSet<T> emptySet() {
     return DEFAULT_INSTANCE;
     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. */
   /** Make this FieldSet immutable from this point forward. */
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
   public void makeImmutable() {
   public void makeImmutable() {
-    for (Map.Entry<FieldDescriptor, Object> entry: fields.entrySet()) {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
       if (entry.getKey().isRepeated()) {
       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);
     fields = Collections.unmodifiableMap(fields);
@@ -98,56 +122,52 @@ final class FieldSet {
     fields.clear();
     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);
     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.
    * 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();
     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(
       throw new IllegalArgumentException(
         "hasField() can only be called on non-repeated fields.");
         "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")
   @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)) {
       if (!(value instanceof List)) {
         throw new IllegalArgumentException(
         throw new IllegalArgumentException(
           "Wrong object type used with protocol message reflection.");
           "Wrong object type used with protocol message reflection.");
@@ -155,78 +175,108 @@ final class FieldSet {
 
 
       // Wrap the contents in a new list so that the caller cannot change
       // Wrap the contents in a new list so that the caller cannot change
       // the list's contents after setting it.
       // the list's contents after setting it.
-      List newList = new ArrayList();
+      final List newList = new ArrayList();
       newList.addAll((List)value);
       newList.addAll((List)value);
-      for (Object element : newList) {
-        verifyType(field, element);
+      for (final Object element : newList) {
+        verifyType(descriptor.getLiteType(), element);
       }
       }
       value = newList;
       value = newList;
     } else {
     } 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()) {
+  /**
+   * Useful for implementing
+   * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}.
+   */
+  public int getRepeatedFieldCount(final FieldDescriptorType descriptor) {
+    if (!descriptor.isRepeated()) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
-        "getRepeatedFieldCount() can only be called on repeated fields.");
+        "getRepeatedField() can only be called on repeated fields.");
     }
     }
 
 
-    return ((List)getField(field)).size();
+    final Object value = fields.get(descriptor);
+    if (value == null) {
+      return 0;
+    } else {
+      return ((List) value).size();
+    }
   }
   }
 
 
-  /** See {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */
-  public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
-    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(
       throw new IllegalArgumentException(
         "getRepeatedField() can only be called on repeated fields.");
         "getRepeatedField() can only be called on repeated fields.");
     }
     }
 
 
-    return ((List)getField(field)).get(index);
+    final Object value = fields.get(descriptor);
+
+    if (value == null) {
+      throw new IndexOutOfBoundsException();
+    } else {
+      return ((List) value).get(index);
+    }
   }
   }
 
 
-  /** See {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. */
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}.
+   */
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
-  public void setRepeatedField(Descriptors.FieldDescriptor field, int index,
-                               Object value) {
-    if (!field.isRepeated()) {
+  public void setRepeatedField(final FieldDescriptorType descriptor,
+                               final int index,
+                               final Object value) {
+    if (!descriptor.isRepeated()) {
       throw new IllegalArgumentException(
       throw new IllegalArgumentException(
-        "setRepeatedField() can only be called on repeated fields.");
+        "getRepeatedField() can only be called on repeated fields.");
     }
     }
 
 
-    verifyType(field, value);
-
-    List list = (List)fields.get(field);
+    final Object list = fields.get(descriptor);
     if (list == null) {
     if (list == null) {
       throw new IndexOutOfBoundsException();
       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")
   @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(
       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();
       list = new ArrayList();
-      fields.put(field, list);
+      fields.put(descriptor, list);
+    } else {
+      list = (List) existingValue;
     }
     }
 
 
     list.add(value);
     list.add(value);
@@ -239,9 +289,14 @@ final class FieldSet {
    *
    *
    * @throws IllegalArgumentException The value is not of the right type.
    * @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;
     boolean isValid = false;
-    switch (field.getJavaType()) {
+    switch (type.getJavaType()) {
       case INT:          isValid = value instanceof Integer   ; break;
       case INT:          isValid = value instanceof Integer   ; break;
       case LONG:         isValid = value instanceof Long      ; break;
       case LONG:         isValid = value instanceof Long      ; break;
       case FLOAT:        isValid = value instanceof Float     ; break;
       case FLOAT:        isValid = value instanceof Float     ; break;
@@ -250,26 +305,25 @@ final class FieldSet {
       case STRING:       isValid = value instanceof String    ; break;
       case STRING:       isValid = value instanceof String    ; break;
       case BYTE_STRING:  isValid = value instanceof ByteString; break;
       case BYTE_STRING:  isValid = value instanceof ByteString; break;
       case ENUM:
       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;
         break;
       case MESSAGE:
       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;
         break;
     }
     }
 
 
     if (!isValid) {
     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(
       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 @@ final class FieldSet {
    */
    */
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
   public boolean isInitialized() {
   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()) {
             if (!element.isInitialized()) {
               return false;
               return false;
             }
             }
           }
           }
         } else {
         } else {
-          if (!((Message) entry.getValue()).isInitialized()) {
+          if (!((MessageLite) entry.getValue()).isInitialized()) {
             return false;
             return false;
           }
           }
         }
         }
@@ -305,59 +361,17 @@ final class FieldSet {
   }
   }
 
 
   /**
   /**
-   * 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,360 +379,334 @@ final class FieldSet {
    * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
    * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
    */
    */
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
-  public void mergeFrom(FieldSet other) {
-    for (Map.Entry<FieldDescriptor, Object> entry : other.fields.entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      Object value = entry.getValue();
-
-      if (field.isRepeated()) {
-        List existingValue = (List)fields.get(field);
-        if (existingValue == null) {
-          existingValue = new ArrayList();
-          fields.put(field, existingValue);
+  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 (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 {
+          // Concatenate the lists.
+          ((List) value).addAll((List) otherValue);
         }
         }
-        existingValue.addAll((List)value);
-      } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        Message existingValue = (Message)fields.get(field);
-        if (existingValue == null) {
-          setField(field, value);
+      } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+        Object value = fields.get(descriptor);
+        if (value == null) {
+          fields.put(descriptor, otherValue);
         } else {
         } else {
-          setField(field,
-            existingValue.toBuilder()
-              .mergeFrom((Message)value)
+          // Merge the messages.
+          fields.put(descriptor,
+              descriptor.internalMergeFrom(
+                ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
               .build());
               .build());
         }
         }
+
       } else {
       } 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;
-      }
+  public static Object readPrimitiveField(
+      CodedInputStream input,
+      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  ();
+
+      case GROUP:
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle nested groups.");
+      case MESSAGE:
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle embedded messages.");
+      case ENUM:
+        // We don't handle enums because we don't know what to do if the
+        // value is not recognized.
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle enums.");
+    }
 
 
-      if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
-                          builder, tag)) {
-        // end group tag
-        break;
-      }
+    throw new RuntimeException(
+      "There is no way to get here, but the compiler thinks otherwise.");
+  }
+
+  /** See {@link Message#writeTo(CodedOutputStream)}. */
+  public void writeTo(final CodedOutputStream output)
+                      throws IOException {
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
+      writeField(entry.getKey(), entry.getValue(), output);
     }
     }
   }
   }
 
 
   /**
   /**
-   * 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.
+   * Like {@link #writeTo} but uses MessageSet wire format.
    */
    */
-  @SuppressWarnings("unchecked")
-  public static boolean mergeFieldFrom(
-      CodedInputStream input,
-      UnknownFieldSet.Builder unknownFields,
-      ExtensionRegistry extensionRegistry,
-      Message.Builder builder,
-      int tag) throws java.io.IOException {
-    Descriptor type = builder.getDescriptorForType();
-
-    if (type.getOptions().getMessageSetWireFormat() &&
-        tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
-      mergeMessageSetExtensionFromCodedStream(
-        input, unknownFields, extensionRegistry, builder);
-      return true;
-    }
-
-    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;
+  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 {
       } else {
-        field = extension.descriptor;
-        defaultInstance = extension.defaultInstance;
+        writeField(descriptor, entry.getValue(), output);
       }
       }
-    } else {
-      field = type.findFieldByNumber(fieldNumber);
     }
     }
+  }
 
 
-    if (field == null ||
-        wireType != WireFormat.getWireFormatForField(field)) {
-      // Unknown field or wrong wire type.  Skip.
-      return unknownFields.mergeFieldFrom(tag, input);
+  /**
+   * 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 {
     } 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);
-        }
-      }
+      output.writeTag(number, getWireFormatForFieldType(type, false));
+      writeElementNoTag(output, type, 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) {
+  /**
+   * 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;
         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;
-            }
-          }
+  /** 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);
         }
         }
-      } 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);
+        output.writeRawVarint32(dataSize);
+        // Write the data itself, without any tags.
+        for (final Object element : valueList) {
+          writeElementNoTag(output, type, element);
         }
         }
       } else {
       } else {
-        // Unknown tag.  Skip it.
-        if (!input.skipField(tag)) {
-          break;  // end of group
+        for (final Object element : valueList) {
+          writeElement(output, type, number, element);
         }
         }
       }
       }
-    }
-
-    input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
-
-    if (subBuilder != null) {
-      builder.setField(field, subBuilder.build());
+    } else {
+      writeElement(output, type, number, value);
     }
     }
   }
   }
 
 
-  /** See {@link Message#writeTo(CodedOutputStream)}. */
-  public void writeTo(CodedOutputStream output)
-                      throws java.io.IOException {
-    for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
-      writeField(entry.getKey(), entry.getValue(), output);
+  /**
+   * See {@link Message#getSerializedSize()}.  It's up to the caller to cache
+   * the resulting size if desired.
+   */
+  public int getSerializedSize() {
+    int size = 0;
+    for (final Map.Entry<FieldDescriptorType, Object> entry:
+         fields.entrySet()) {
+      size += computeFieldSize(entry.getKey(), entry.getValue());
     }
     }
+    return size;
   }
   }
 
 
-  /** 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);
-    } 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);
-          }
-        }
+  /**
+   * 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(
+                  entry.getKey().getNumber(), (MessageLite) entry.getValue());
       } else {
       } else {
-        output.writeField(field.getType(), field.getNumber(), value);
+        size += computeFieldSize(descriptor, entry.getValue());
       }
       }
     }
     }
+    return size;
   }
   }
 
 
   /**
   /**
-   * See {@link Message#getSerializedSize()}.  It's up to the caller to cache
-   * the resulting size if desired.
+   * 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.
    */
    */
-  public int getSerializedSize() {
-    int size = 0;
-    for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
-      FieldDescriptor field = entry.getKey();
-      Object value = entry.getValue();
+  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);
+  }
 
 
-      if (field.isExtension() &&
-          field.getContainingType().getOptions().getMessageSetWireFormat()) {
-        size += CodedOutputStream.computeMessageSetExtensionSize(
-          field.getNumber(), (Message) 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 {
       } 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);
+        int size = 0;
+        for (final Object element : (List)value) {
+          size += computeElementSize(type, number, element);
         }
         }
+        return size;
       }
       }
+    } else {
+      return computeElementSize(type, number, value);
     }
     }
-    return size;
   }
   }
 }
 }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 249 - 224
java/src/main/java/com/google/protobuf/GeneratedMessage.java


+ 539 - 0
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;
+    }
+  }
+}

+ 194 - 0
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);
+  }
+}

+ 3 - 1
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java

@@ -39,7 +39,9 @@ import java.io.IOException;
  * @author kenton@google.com Kenton Varda
  * @author kenton@google.com Kenton Varda
  */
  */
 public class InvalidProtocolBufferException extends IOException {
 public class InvalidProtocolBufferException extends IOException {
-  public InvalidProtocolBufferException(String description) {
+  private static final long serialVersionUID = -1616151763072450476L;
+
+  public InvalidProtocolBufferException(final String description) {
     super(description);
     super(description);
   }
   }
 
 

+ 31 - 216
java/src/main/java/com/google/protobuf/Message.java

@@ -33,17 +33,22 @@
 
 
 package com.google.protobuf;
 package com.google.protobuf;
 
 
-import java.io.InputStream;
 import java.io.IOException;
 import java.io.IOException;
-import java.io.OutputStream;
+import java.io.InputStream;
 import java.util.Map;
 import java.util.Map;
 
 
 /**
 /**
  * Abstract interface implemented by Protocol Message objects.
  * 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
  * @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
    * Get the message's type's descriptor.  This differs from the
    * {@code getDescriptor()} method of generated message classes in that
    * {@code getDescriptor()} method of generated message classes in that
@@ -53,14 +58,7 @@ public interface Message {
    */
    */
   Descriptors.Descriptor getDescriptorForType();
   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();
   Message getDefaultInstanceForType();
 
 
   /**
   /**
@@ -114,24 +112,6 @@ public interface Message {
   /** Get the {@link UnknownFieldSet} for this message. */
   /** Get the {@link UnknownFieldSet} for this message. */
   UnknownFieldSet getUnknownFields();
   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
   // Comparison and hashing
 
 
@@ -144,6 +124,7 @@ public interface Message {
    * @param other object to be compared for equality with this message
    * @param other object to be compared for equality with this message
    * @return <tt>true</tt> if the specified object is equal to this message
    * @return <tt>true</tt> if the specified object is equal to this message
    */
    */
+  @Override
   boolean equals(Object other);
   boolean equals(Object other);
 
 
   /**
   /**
@@ -154,6 +135,7 @@ public interface Message {
    * @return the hash code value for this message
    * @return the hash code value for this message
    * @see Map#hashCode()
    * @see Map#hashCode()
    */
    */
+  @Override
   int hashCode();
   int hashCode();
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
@@ -163,67 +145,22 @@ public interface Message {
    * Converts the message to a string in protocol buffer text format. This is
    * Converts the message to a string in protocol buffer text format. This is
    * just a trivial wrapper around {@link TextFormat#printToString(Message)}.
    * just a trivial wrapper around {@link TextFormat#printToString(Message)}.
    */
    */
+  @Override
   String toString();
   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
   // 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();
   Builder newBuilderForType();
-
-  /**
-   * Constructs a builder initialized with the current message.  Use this to
-   * derive a new message from the current one.
-   */
   Builder toBuilder();
   Builder toBuilder();
 
 
   /**
   /**
    * Abstract interface implemented by Protocol Message builders.
    * 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();
     Builder clear();
 
 
     /**
     /**
@@ -244,71 +181,14 @@ public interface Message {
      */
      */
     Builder mergeFrom(Message other);
     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();
     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();
     Message buildPartial();
-
-    /**
-     * Clones the Builder.
-     * @see Object#clone()
-     */
     Builder 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;
     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,
     Builder mergeFrom(CodedInputStream input,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws IOException;
                       throws IOException;
 
 
     /**
     /**
@@ -317,10 +197,8 @@ public interface Message {
      */
      */
     Descriptors.Descriptor getDescriptorForType();
     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();
     Message getDefaultInstanceForType();
 
 
     /**
     /**
@@ -399,92 +277,29 @@ public interface Message {
     // ---------------------------------------------------------------
     // ---------------------------------------------------------------
     // Convenience methods.
     // 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;
     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,
     Builder mergeFrom(ByteString data,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+    Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+    Builder mergeFrom(byte[] data, int off, int len)
                       throws InvalidProtocolBufferException;
                       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,
     Builder mergeFrom(byte[] data,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws InvalidProtocolBufferException;
                       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,
     Builder mergeFrom(byte[] data, int off, int len,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws InvalidProtocolBufferException;
                       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;
     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,
     Builder mergeFrom(InputStream input,
-                      ExtensionRegistry extensionRegistry)
+                      ExtensionRegistryLite extensionRegistry)
                       throws IOException;
                       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)
     Builder mergeDelimitedFrom(InputStream input)
                                throws IOException;
                                throws IOException;
-
-    /**
-     * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
-     */
     Builder mergeDelimitedFrom(InputStream input,
     Builder mergeDelimitedFrom(InputStream input,
-                               ExtensionRegistry extensionRegistry)
+                               ExtensionRegistryLite extensionRegistry)
                                throws IOException;
                                throws IOException;
   }
   }
 }
 }

+ 331 - 0
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;
+  }
+}

+ 1 - 1
java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java

@@ -37,7 +37,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
  * Interface of useful methods added to all enums generated by the protocol
  * Interface of useful methods added to all enums generated by the protocol
  * compiler.
  * compiler.
  */
  */
-public interface ProtocolMessageEnum {
+public interface ProtocolMessageEnum extends Internal.EnumLite {
 
 
   /**
   /**
    * Return the value's numeric value as defined in the .proto file.
    * Return the value's numeric value as defined in the .proto file.

+ 8 - 5
java/src/main/java/com/google/protobuf/RpcUtil.java

@@ -71,11 +71,11 @@ public final class RpcUtil {
       final Class<Type> originalClass,
       final Class<Type> originalClass,
       final Type defaultInstance) {
       final Type defaultInstance) {
     return new RpcCallback<Message>() {
     return new RpcCallback<Message>() {
-      public void run(Message parameter) {
+      public void run(final Message parameter) {
         Type typedParameter;
         Type typedParameter;
         try {
         try {
           typedParameter = originalClass.cast(parameter);
           typedParameter = originalClass.cast(parameter);
-        } catch (ClassCastException e) {
+        } catch (ClassCastException ignored) {
           typedParameter = copyAsType(defaultInstance, parameter);
           typedParameter = copyAsType(defaultInstance, parameter);
         }
         }
         originalCallback.run(typedParameter);
         originalCallback.run(typedParameter);
@@ -90,7 +90,7 @@ public final class RpcUtil {
    */
    */
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
   private static <Type extends Message> Type copyAsType(
   private static <Type extends Message> Type copyAsType(
-      Type typeDefaultInstance, Message source) {
+      final Type typeDefaultInstance, final Message source) {
     return (Type)typeDefaultInstance.newBuilderForType()
     return (Type)typeDefaultInstance.newBuilderForType()
                                     .mergeFrom(source)
                                     .mergeFrom(source)
                                     .build();
                                     .build();
@@ -106,8 +106,9 @@ public final class RpcUtil {
     RpcCallback<ParameterType> newOneTimeCallback(
     RpcCallback<ParameterType> newOneTimeCallback(
       final RpcCallback<ParameterType> originalCallback) {
       final RpcCallback<ParameterType> originalCallback) {
     return new RpcCallback<ParameterType>() {
     return new RpcCallback<ParameterType>() {
-      boolean alreadyCalled = false;
-      public void run(ParameterType parameter) {
+      private boolean alreadyCalled = false;
+
+      public void run(final ParameterType parameter) {
         synchronized(this) {
         synchronized(this) {
           if (alreadyCalled) {
           if (alreadyCalled) {
             throw new AlreadyCalledException();
             throw new AlreadyCalledException();
@@ -124,6 +125,8 @@ public final class RpcUtil {
    * Exception thrown when a one-time callback is called more than once.
    * Exception thrown when a one-time callback is called more than once.
    */
    */
   public static final class AlreadyCalledException extends RuntimeException {
   public static final class AlreadyCalledException extends RuntimeException {
+    private static final long serialVersionUID = 5469741279507848266L;
+
     public AlreadyCalledException() {
     public AlreadyCalledException() {
       super("This RpcCallback was already called and cannot be called " +
       super("This RpcCallback was already called and cannot be called " +
             "multiple times.");
             "multiple times.");

+ 4 - 2
java/src/main/java/com/google/protobuf/ServiceException.java

@@ -32,11 +32,13 @@ package com.google.protobuf;
 
 
 /**
 /**
  * Thrown by blocking RPC methods when a failure occurs.
  * Thrown by blocking RPC methods when a failure occurs.
- * 
+ *
  * @author cpovirk@google.com (Chris Povirk)
  * @author cpovirk@google.com (Chris Povirk)
  */
  */
 public final class ServiceException extends Exception {
 public final class ServiceException extends Exception {
-  public ServiceException(String message) {
+  private static final long serialVersionUID = -1219262335729891920L;
+
+  public ServiceException(final String message) {
     super(message);
     super(message);
   }
   }
 }
 }

+ 164 - 132
java/src/main/java/com/google/protobuf/TextFormat.java

@@ -52,22 +52,25 @@ import java.util.regex.Pattern;
  * @author kenton@google.com Kenton Varda
  * @author kenton@google.com Kenton Varda
  */
  */
 public final class TextFormat {
 public final class TextFormat {
+  private TextFormat() {
+  }
 
 
   /**
   /**
    * Outputs a textual representation of the Protocol Message supplied into
    * Outputs a textual representation of the Protocol Message supplied into
    * the parameter output. (This representation is the new version of the
    * the parameter output. (This representation is the new version of the
    * classic "ProtocolPrinter" output from the original Protocol Buffer system)
    * 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 {
                            throws IOException {
-    TextGenerator generator = new TextGenerator(output);
+    final TextGenerator generator = new TextGenerator(output);
     print(message, generator);
     print(message, generator);
   }
   }
 
 
   /** Outputs a textual representation of {@code fields} to {@code output}. */
   /** 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 {
                            throws IOException {
-    TextGenerator generator = new TextGenerator(output);
+    final TextGenerator generator = new TextGenerator(output);
     printUnknownFields(fields, generator);
     printUnknownFields(fields, generator);
   }
   }
 
 
@@ -75,9 +78,9 @@ public final class TextFormat {
    * Like {@code print()}, but writes directly to a {@code String} and
    * Like {@code print()}, but writes directly to a {@code String} and
    * returns it.
    * returns it.
    */
    */
-  public static String printToString(Message message) {
+  public static String printToString(final Message message) {
     try {
     try {
-      StringBuilder text = new StringBuilder();
+      final StringBuilder text = new StringBuilder();
       print(message, text);
       print(message, text);
       return text.toString();
       return text.toString();
     } catch (IOException e) {
     } catch (IOException e) {
@@ -91,9 +94,9 @@ public final class TextFormat {
    * Like {@code print()}, but writes directly to a {@code String} and
    * Like {@code print()}, but writes directly to a {@code String} and
    * returns it.
    * returns it.
    */
    */
-  public static String printToString(UnknownFieldSet fields) {
+  public static String printToString(final UnknownFieldSet fields) {
     try {
     try {
-      StringBuilder text = new StringBuilder();
+      final StringBuilder text = new StringBuilder();
       print(fields, text);
       print(fields, text);
       return text.toString();
       return text.toString();
     } catch (IOException e) {
     } catch (IOException e) {
@@ -103,22 +106,44 @@ public final class TextFormat {
     }
     }
   }
   }
 
 
-  private static void print(Message message, TextGenerator generator)
+  private static void print(final Message message,
+                            final TextGenerator generator)
       throws IOException {
       throws IOException {
-    for (Map.Entry<FieldDescriptor, Object> field :
+    for (final Map.Entry<FieldDescriptor, Object> field :
          message.getAllFields().entrySet()) {
          message.getAllFields().entrySet()) {
       printField(field.getKey(), field.getValue(), generator);
       printField(field.getKey(), field.getValue(), generator);
     }
     }
     printUnknownFields(message.getUnknownFields(), 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 {
                                 throws IOException {
     if (field.isRepeated()) {
     if (field.isRepeated()) {
       // Repeated field.  Print each element.
       // Repeated field.  Print each element.
-      for (Object element : (List) value) {
+      for (final Object element : (List) value) {
         printSingleField(field, element, generator);
         printSingleField(field, element, generator);
       }
       }
     } else {
     } else {
@@ -126,9 +151,9 @@ public final class TextFormat {
     }
     }
   }
   }
 
 
-  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 {
                                        throws IOException {
     if (field.isExtension()) {
     if (field.isExtension()) {
       generator.print("[");
       generator.print("[");
@@ -168,9 +193,9 @@ public final class TextFormat {
     generator.print("\n");
     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 {
                                       throws IOException {
     switch (field.getType()) {
     switch (field.getType()) {
       case INT32:
       case INT32:
@@ -202,17 +227,15 @@ public final class TextFormat {
         generator.print("\"");
         generator.print("\"");
         break;
         break;
 
 
-      case BYTES: {
+      case BYTES:
         generator.print("\"");
         generator.print("\"");
         generator.print(escapeBytes((ByteString) value));
         generator.print(escapeBytes((ByteString) value));
         generator.print("\"");
         generator.print("\"");
         break;
         break;
-      }
 
 
-      case ENUM: {
+      case ENUM:
         generator.print(((EnumValueDescriptor) value).getName());
         generator.print(((EnumValueDescriptor) value).getName());
         break;
         break;
-      }
 
 
       case MESSAGE:
       case MESSAGE:
       case GROUP:
       case GROUP:
@@ -221,39 +244,39 @@ public final class TextFormat {
     }
     }
   }
   }
 
 
-  private static void printUnknownFields(UnknownFieldSet unknownFields,
-                                         TextGenerator generator)
+  private static void printUnknownFields(final UnknownFieldSet unknownFields,
+                                         final TextGenerator generator)
                                          throws IOException {
                                          throws IOException {
-    for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+    for (final Map.Entry<Integer, UnknownFieldSet.Field> entry :
          unknownFields.asMap().entrySet()) {
          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(entry.getKey().toString());
         generator.print(": ");
         generator.print(": ");
         generator.print(unsignedToString(value));
         generator.print(unsignedToString(value));
         generator.print("\n");
         generator.print("\n");
       }
       }
-      for (int value : field.getFixed32List()) {
+      for (final int value : field.getFixed32List()) {
         generator.print(entry.getKey().toString());
         generator.print(entry.getKey().toString());
         generator.print(": ");
         generator.print(": ");
         generator.print(String.format((Locale) null, "0x%08x", value));
         generator.print(String.format((Locale) null, "0x%08x", value));
         generator.print("\n");
         generator.print("\n");
       }
       }
-      for (long value : field.getFixed64List()) {
+      for (final long value : field.getFixed64List()) {
         generator.print(entry.getKey().toString());
         generator.print(entry.getKey().toString());
         generator.print(": ");
         generator.print(": ");
         generator.print(String.format((Locale) null, "0x%016x", value));
         generator.print(String.format((Locale) null, "0x%016x", value));
         generator.print("\n");
         generator.print("\n");
       }
       }
-      for (ByteString value : field.getLengthDelimitedList()) {
+      for (final ByteString value : field.getLengthDelimitedList()) {
         generator.print(entry.getKey().toString());
         generator.print(entry.getKey().toString());
         generator.print(": \"");
         generator.print(": \"");
         generator.print(escapeBytes(value));
         generator.print(escapeBytes(value));
         generator.print("\"\n");
         generator.print("\"\n");
       }
       }
-      for (UnknownFieldSet value : field.getGroupList()) {
+      for (final UnknownFieldSet value : field.getGroupList()) {
         generator.print(entry.getKey().toString());
         generator.print(entry.getKey().toString());
         generator.print(" {\n");
         generator.print(" {\n");
         generator.indent();
         generator.indent();
@@ -265,7 +288,7 @@ public final class TextFormat {
   }
   }
 
 
   /** Convert an unsigned 32-bit integer to a string. */
   /** 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) {
     if (value >= 0) {
       return Integer.toString(value);
       return Integer.toString(value);
     } else {
     } else {
@@ -274,7 +297,7 @@ public final class TextFormat {
   }
   }
 
 
   /** Convert an unsigned 64-bit integer to a string. */
   /** 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) {
     if (value >= 0) {
       return Long.toString(value);
       return Long.toString(value);
     } else {
     } else {
@@ -288,13 +311,12 @@ public final class TextFormat {
   /**
   /**
    * An inner class for writing text to the output stream.
    * 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;
       this.output = output;
     }
     }
 
 
@@ -312,7 +334,7 @@ public final class TextFormat {
      * level is zero.
      * level is zero.
      */
      */
     public void outdent() {
     public void outdent() {
-      int length = indent.length();
+      final int length = indent.length();
       if (length == 0) {
       if (length == 0) {
         throw new IllegalArgumentException(
         throw new IllegalArgumentException(
             " Outdent() without matching Indent().");
             " Outdent() without matching Indent().");
@@ -323,8 +345,8 @@ public final class TextFormat {
     /**
     /**
      * Print text to the output stream.
      * 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;
       int pos = 0;
 
 
       for (int i = 0; i < size; i++) {
       for (int i = 0; i < size; i++) {
@@ -337,7 +359,8 @@ public final class TextFormat {
       write(text.subSequence(pos, size), size - pos);
       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) {
       if (size == 0) {
         return;
         return;
       }
       }
@@ -399,27 +422,27 @@ public final class TextFormat {
 
 
     // We use possesive quantifiers (*+ and ++) because otherwise the Java
     // We use possesive quantifiers (*+ and ++) because otherwise the Java
     // regex matcher has stack overflows on large inputs.
     // regex matcher has stack overflows on large inputs.
-    private static Pattern WHITESPACE =
+    private static final Pattern WHITESPACE =
       Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
       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
       "[a-zA-Z_][0-9a-zA-Z_+-]*+|" +                // an identifier
       "[0-9+-][0-9a-zA-Z_.+-]*+|" +                 // a number
       "[0-9+-][0-9a-zA-Z_.+-]*+|" +                 // a number
       "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" +       // a double-quoted string
       "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" +       // a double-quoted string
       "\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)",         // a single-quoted string
       "\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)",         // a single-quoted string
       Pattern.MULTILINE);
       Pattern.MULTILINE);
 
 
-    private static Pattern DOUBLE_INFINITY = Pattern.compile(
+    private static final Pattern DOUBLE_INFINITY = Pattern.compile(
       "-?inf(inity)?",
       "-?inf(inity)?",
       Pattern.CASE_INSENSITIVE);
       Pattern.CASE_INSENSITIVE);
-    private static Pattern FLOAT_INFINITY = Pattern.compile(
+    private static final Pattern FLOAT_INFINITY = Pattern.compile(
       "-?inf(inity)?f?",
       "-?inf(inity)?f?",
       Pattern.CASE_INSENSITIVE);
       Pattern.CASE_INSENSITIVE);
-    private static Pattern FLOAT_NAN = Pattern.compile(
+    private static final Pattern FLOAT_NAN = Pattern.compile(
       "nanf?",
       "nanf?",
       Pattern.CASE_INSENSITIVE);
       Pattern.CASE_INSENSITIVE);
 
 
     /** Construct a tokenizer that parses tokens from the given text. */
     /** Construct a tokenizer that parses tokens from the given text. */
-    public Tokenizer(CharSequence text) {
+    private Tokenizer(final CharSequence text) {
       this.text = text;
       this.text = text;
       this.matcher = WHITESPACE.matcher(text);
       this.matcher = WHITESPACE.matcher(text);
       skipWhitespace();
       skipWhitespace();
@@ -481,7 +504,7 @@ public final class TextFormat {
      * If the next token exactly matches {@code token}, consume it and return
      * If the next token exactly matches {@code token}, consume it and return
      * {@code true}.  Otherwise, return {@code false} without doing anything.
      * {@code true}.  Otherwise, return {@code false} without doing anything.
      */
      */
-    public boolean tryConsume(String token) {
+    public boolean tryConsume(final String token) {
       if (currentToken.equals(token)) {
       if (currentToken.equals(token)) {
         nextToken();
         nextToken();
         return true;
         return true;
@@ -494,7 +517,7 @@ public final class TextFormat {
      * If the next token exactly matches {@code token}, consume it.  Otherwise,
      * If the next token exactly matches {@code token}, consume it.  Otherwise,
      * throw a {@link ParseException}.
      * throw a {@link ParseException}.
      */
      */
-    public void consume(String token) throws ParseException {
+    public void consume(final String token) throws ParseException {
       if (!tryConsume(token)) {
       if (!tryConsume(token)) {
         throw parseException("Expected \"" + token + "\".");
         throw parseException("Expected \"" + token + "\".");
       }
       }
@@ -509,7 +532,7 @@ public final class TextFormat {
         return false;
         return false;
       }
       }
 
 
-      char c = currentToken.charAt(0);
+      final char c = currentToken.charAt(0);
       return ('0' <= c && c <= '9') ||
       return ('0' <= c && c <= '9') ||
              c == '-' || c == '+';
              c == '-' || c == '+';
     }
     }
@@ -520,7 +543,7 @@ public final class TextFormat {
      */
      */
     public String consumeIdentifier() throws ParseException {
     public String consumeIdentifier() throws ParseException {
       for (int i = 0; i < currentToken.length(); i++) {
       for (int i = 0; i < currentToken.length(); i++) {
-        char c = currentToken.charAt(i);
+        final char c = currentToken.charAt(i);
         if (('a' <= c && c <= 'z') ||
         if (('a' <= c && c <= 'z') ||
             ('A' <= c && c <= 'Z') ||
             ('A' <= c && c <= 'Z') ||
             ('0' <= c && c <= '9') ||
             ('0' <= c && c <= '9') ||
@@ -531,7 +554,7 @@ public final class TextFormat {
         }
         }
       }
       }
 
 
-      String result = currentToken;
+      final String result = currentToken;
       nextToken();
       nextToken();
       return result;
       return result;
     }
     }
@@ -542,7 +565,7 @@ public final class TextFormat {
      */
      */
     public int consumeInt32() throws ParseException {
     public int consumeInt32() throws ParseException {
       try {
       try {
-        int result = parseInt32(currentToken);
+        final int result = parseInt32(currentToken);
         nextToken();
         nextToken();
         return result;
         return result;
       } catch (NumberFormatException e) {
       } catch (NumberFormatException e) {
@@ -556,7 +579,7 @@ public final class TextFormat {
      */
      */
     public int consumeUInt32() throws ParseException {
     public int consumeUInt32() throws ParseException {
       try {
       try {
-        int result = parseUInt32(currentToken);
+        final int result = parseUInt32(currentToken);
         nextToken();
         nextToken();
         return result;
         return result;
       } catch (NumberFormatException e) {
       } catch (NumberFormatException e) {
@@ -570,7 +593,7 @@ public final class TextFormat {
      */
      */
     public long consumeInt64() throws ParseException {
     public long consumeInt64() throws ParseException {
       try {
       try {
-        long result = parseInt64(currentToken);
+        final long result = parseInt64(currentToken);
         nextToken();
         nextToken();
         return result;
         return result;
       } catch (NumberFormatException e) {
       } catch (NumberFormatException e) {
@@ -584,7 +607,7 @@ public final class TextFormat {
      */
      */
     public long consumeUInt64() throws ParseException {
     public long consumeUInt64() throws ParseException {
       try {
       try {
-        long result = parseUInt64(currentToken);
+        final long result = parseUInt64(currentToken);
         nextToken();
         nextToken();
         return result;
         return result;
       } catch (NumberFormatException e) {
       } catch (NumberFormatException e) {
@@ -600,7 +623,7 @@ public final class TextFormat {
       // We need to parse infinity and nan separately because
       // We need to parse infinity and nan separately because
       // Double.parseDouble() does not accept "inf", "infinity", or "nan".
       // Double.parseDouble() does not accept "inf", "infinity", or "nan".
       if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
       if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
-        boolean negative = currentToken.startsWith("-");
+        final boolean negative = currentToken.startsWith("-");
         nextToken();
         nextToken();
         return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
         return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
       }
       }
@@ -609,7 +632,7 @@ public final class TextFormat {
         return Double.NaN;
         return Double.NaN;
       }
       }
       try {
       try {
-        double result = Double.parseDouble(currentToken);
+        final double result = Double.parseDouble(currentToken);
         nextToken();
         nextToken();
         return result;
         return result;
       } catch (NumberFormatException e) {
       } catch (NumberFormatException e) {
@@ -625,7 +648,7 @@ public final class TextFormat {
       // We need to parse infinity and nan separately because
       // We need to parse infinity and nan separately because
       // Float.parseFloat() does not accept "inf", "infinity", or "nan".
       // Float.parseFloat() does not accept "inf", "infinity", or "nan".
       if (FLOAT_INFINITY.matcher(currentToken).matches()) {
       if (FLOAT_INFINITY.matcher(currentToken).matches()) {
-        boolean negative = currentToken.startsWith("-");
+        final boolean negative = currentToken.startsWith("-");
         nextToken();
         nextToken();
         return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
         return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
       }
       }
@@ -634,7 +657,7 @@ public final class TextFormat {
         return Float.NaN;
         return Float.NaN;
       }
       }
       try {
       try {
-        float result = Float.parseFloat(currentToken);
+        final float result = Float.parseFloat(currentToken);
         nextToken();
         nextToken();
         return result;
         return result;
       } catch (NumberFormatException e) {
       } catch (NumberFormatException e) {
@@ -672,7 +695,8 @@ public final class TextFormat {
      * {@link ParseException}.
      * {@link ParseException}.
      */
      */
     public ByteString consumeByteString() throws 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 != '\'') {
       if (quote != '\"' && quote != '\'') {
         throw parseException("Expected string.");
         throw parseException("Expected string.");
       }
       }
@@ -683,11 +707,12 @@ public final class TextFormat {
       }
       }
 
 
       try {
       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();
         nextToken();
         return result;
         return result;
-      } catch (InvalidEscapeSequence e) {
+      } catch (InvalidEscapeSequenceException e) {
         throw parseException(e.getMessage());
         throw parseException(e.getMessage());
       }
       }
     }
     }
@@ -696,7 +721,7 @@ public final class TextFormat {
      * Returns a {@link ParseException} with the current line and column
      * Returns a {@link ParseException} with the current line and column
      * numbers in the description, suitable for throwing.
      * 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.
       // Note:  People generally prefer one-based line and column numbers.
       return new ParseException(
       return new ParseException(
         (line + 1) + ":" + (column + 1) + ": " + description);
         (line + 1) + ":" + (column + 1) + ": " + description);
@@ -706,7 +731,8 @@ public final class TextFormat {
      * Returns a {@link ParseException} with the line and column numbers of
      * Returns a {@link ParseException} with the line and column numbers of
      * the previous token in the description, suitable for throwing.
      * 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.
       // Note:  People generally prefer one-based line and column numbers.
       return new ParseException(
       return new ParseException(
         (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
         (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
@@ -716,7 +742,8 @@ public final class TextFormat {
      * Constructs an appropriate {@link ParseException} for the given
      * Constructs an appropriate {@link ParseException} for the given
      * {@code NumberFormatException} when trying to parse an integer.
      * {@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());
       return parseException("Couldn't parse integer: " + e.getMessage());
     }
     }
 
 
@@ -724,14 +751,16 @@ public final class TextFormat {
      * Constructs an appropriate {@link ParseException} for the given
      * Constructs an appropriate {@link ParseException} for the given
      * {@code NumberFormatException} when trying to parse a float or double.
      * {@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());
       return parseException("Couldn't parse number: " + e.getMessage());
     }
     }
   }
   }
 
 
   /** Thrown when parsing an invalid text format message. */
   /** Thrown when parsing an invalid text format message. */
   public static class ParseException extends IOException {
   public static class ParseException extends IOException {
-    public ParseException(String message) {
+    private static final long serialVersionUID = 3196188060225107702L;
+
+    public ParseException(final String message) {
       super(message);
       super(message);
     }
     }
   }
   }
@@ -740,9 +769,9 @@ public final class TextFormat {
    * Parse a text-format message from {@code input} and merge the contents
    * Parse a text-format message from {@code input} and merge the contents
    * into {@code builder}.
    * 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);
     merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
   }
   }
 
 
@@ -750,8 +779,8 @@ public final class TextFormat {
    * Parse a text-format message from {@code input} and merge the contents
    * Parse a text-format message from {@code input} and merge the contents
    * into {@code builder}.
    * 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 {
                            throws ParseException {
     merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
     merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
   }
   }
@@ -761,10 +790,10 @@ public final class TextFormat {
    * into {@code builder}.  Extensions will be recognized if they are
    * into {@code builder}.  Extensions will be recognized if they are
    * registered in {@code extensionRegistry}.
    * 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.
     // Read the entire input to a String then parse that.
 
 
     // If StreamTokenizer were not quite so crippled, or if there were a kind
     // If StreamTokenizer were not quite so crippled, or if there were a kind
@@ -780,12 +809,12 @@ public final class TextFormat {
 
 
   // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
   // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
   // overhead is worthwhile
   // overhead is worthwhile
-  private static StringBuilder toStringBuilder(Readable input)
+  private static StringBuilder toStringBuilder(final Readable input)
       throws IOException {
       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) {
     while (true) {
-      int n = input.read(buffer);
+      final int n = input.read(buffer);
       if (n == -1) {
       if (n == -1) {
         break;
         break;
       }
       }
@@ -800,11 +829,11 @@ public final class TextFormat {
    * into {@code builder}.  Extensions will be recognized if they are
    * into {@code builder}.  Extensions will be recognized if they are
    * registered in {@code extensionRegistry}.
    * 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 {
                            throws ParseException {
-    Tokenizer tokenizer = new Tokenizer(input);
+    final Tokenizer tokenizer = new Tokenizer(input);
 
 
     while (!tokenizer.atEnd()) {
     while (!tokenizer.atEnd()) {
       mergeField(tokenizer, extensionRegistry, builder);
       mergeField(tokenizer, extensionRegistry, builder);
@@ -815,19 +844,20 @@ public final class TextFormat {
    * Parse a single field from {@code tokenizer} and merge it into
    * Parse a single field from {@code tokenizer} and merge it into
    * {@code builder}.
    * {@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 {
                                  throws ParseException {
     FieldDescriptor field;
     FieldDescriptor field;
-    Descriptor type = builder.getDescriptorForType();
+    final Descriptor type = builder.getDescriptorForType();
     ExtensionRegistry.ExtensionInfo extension = null;
     ExtensionRegistry.ExtensionInfo extension = null;
 
 
     if (tokenizer.tryConsume("[")) {
     if (tokenizer.tryConsume("[")) {
       // An extension.
       // An extension.
-      StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier());
+      final StringBuilder name =
+          new StringBuilder(tokenizer.consumeIdentifier());
       while (tokenizer.tryConsume(".")) {
       while (tokenizer.tryConsume(".")) {
-        name.append(".");
+        name.append('.');
         name.append(tokenizer.consumeIdentifier());
         name.append(tokenizer.consumeIdentifier());
       }
       }
 
 
@@ -846,7 +876,7 @@ public final class TextFormat {
 
 
       field = extension.descriptor;
       field = extension.descriptor;
     } else {
     } else {
-      String name = tokenizer.consumeIdentifier();
+      final String name = tokenizer.consumeIdentifier();
       field = type.findFieldByName(name);
       field = type.findFieldByName(name);
 
 
       // Group names are expected to be capitalized as they appear in the
       // Group names are expected to be capitalized as they appear in the
@@ -855,7 +885,7 @@ public final class TextFormat {
       if (field == null) {
       if (field == null) {
         // Explicitly specify US locale so that this code does not break when
         // Explicitly specify US locale so that this code does not break when
         // executing in Turkey.
         // executing in Turkey.
-        String lowerName = name.toLowerCase(Locale.US);
+        final String lowerName = name.toLowerCase(Locale.US);
         field = type.findFieldByName(lowerName);
         field = type.findFieldByName(lowerName);
         // If the case-insensitive match worked but the field is NOT a group,
         // If the case-insensitive match worked but the field is NOT a group,
         if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
         if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
@@ -880,7 +910,7 @@ public final class TextFormat {
     if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
     if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
       tokenizer.tryConsume(":");  // optional
       tokenizer.tryConsume(":");  // optional
 
 
-      String endToken;
+      final String endToken;
       if (tokenizer.tryConsume("<")) {
       if (tokenizer.tryConsume("<")) {
         endToken = ">";
         endToken = ">";
       } else {
       } else {
@@ -888,7 +918,7 @@ public final class TextFormat {
         endToken = "}";
         endToken = "}";
       }
       }
 
 
-      Message.Builder subBuilder;
+      final Message.Builder subBuilder;
       if (extension == null) {
       if (extension == null) {
         subBuilder = builder.newBuilderForField(field);
         subBuilder = builder.newBuilderForField(field);
       } else {
       } else {
@@ -951,19 +981,19 @@ public final class TextFormat {
           value = tokenizer.consumeByteString();
           value = tokenizer.consumeByteString();
           break;
           break;
 
 
-        case ENUM: {
-          EnumDescriptor enumType = field.getEnumType();
+        case ENUM:
+          final EnumDescriptor enumType = field.getEnumType();
 
 
           if (tokenizer.lookingAtInteger()) {
           if (tokenizer.lookingAtInteger()) {
-            int number = tokenizer.consumeInt32();
+            final int number = tokenizer.consumeInt32();
             value = enumType.findValueByNumber(number);
             value = enumType.findValueByNumber(number);
             if (value == null) {
             if (value == null) {
               throw tokenizer.parseExceptionPreviousToken(
               throw tokenizer.parseExceptionPreviousToken(
                 "Enum type \"" + enumType.getFullName() +
                 "Enum type \"" + enumType.getFullName() +
-                "\" has no value with number " + number + ".");
+                "\" has no value with number " + number + '.');
             }
             }
           } else {
           } else {
-            String id = tokenizer.consumeIdentifier();
+            final String id = tokenizer.consumeIdentifier();
             value = enumType.findValueByName(id);
             value = enumType.findValueByName(id);
             if (value == null) {
             if (value == null) {
               throw tokenizer.parseExceptionPreviousToken(
               throw tokenizer.parseExceptionPreviousToken(
@@ -973,7 +1003,6 @@ public final class TextFormat {
           }
           }
 
 
           break;
           break;
-        }
 
 
         case MESSAGE:
         case MESSAGE:
         case GROUP:
         case GROUP:
@@ -1002,10 +1031,10 @@ public final class TextFormat {
    * which no defined short-hand escape sequence is defined will be escaped
    * which no defined short-hand escape sequence is defined will be escaped
    * using 3-digit octal sequences.
    * 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++) {
     for (int i = 0; i < input.size(); i++) {
-      byte b = input.byteAt(i);
+      final byte b = input.byteAt(i);
       switch (b) {
       switch (b) {
         // Java does not recognize \a or \v, apparently.
         // Java does not recognize \a or \v, apparently.
         case 0x07: builder.append("\\a" ); break;
         case 0x07: builder.append("\\a" ); break;
@@ -1038,9 +1067,9 @@ public final class TextFormat {
    * {@link #escapeBytes(ByteString)}.  Two-digit hex escapes (starting with
    * {@link #escapeBytes(ByteString)}.  Two-digit hex escapes (starting with
    * "\x") are also recognized.
    * "\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;
     int pos = 0;
     for (int i = 0; i < input.length(); i++) {
     for (int i = 0; i < input.length(); i++) {
       char c = input.charAt(i);
       char c = input.charAt(i);
@@ -1080,7 +1109,7 @@ public final class TextFormat {
                   ++i;
                   ++i;
                   code = digitValue(input.charAt(i));
                   code = digitValue(input.charAt(i));
                 } else {
                 } else {
-                  throw new InvalidEscapeSequence(
+                  throw new InvalidEscapeSequenceException(
                     "Invalid escape sequence: '\\x' with no digits");
                     "Invalid escape sequence: '\\x' with no digits");
                 }
                 }
                 if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
                 if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
@@ -1091,12 +1120,12 @@ public final class TextFormat {
                 break;
                 break;
 
 
               default:
               default:
-                throw new InvalidEscapeSequence(
-                  "Invalid escape sequence: '\\" + c + "'");
+                throw new InvalidEscapeSequenceException(
+                  "Invalid escape sequence: '\\" + c + '\'');
             }
             }
           }
           }
         } else {
         } else {
-          throw new InvalidEscapeSequence(
+          throw new InvalidEscapeSequenceException(
             "Invalid escape sequence: '\\' at end of string.");
             "Invalid escape sequence: '\\' at end of string.");
         }
         }
       } else {
       } else {
@@ -1111,8 +1140,10 @@ public final class TextFormat {
    * Thrown by {@link TextFormat#unescapeBytes} and
    * Thrown by {@link TextFormat#unescapeBytes} and
    * {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
    * {@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);
       super(description);
     }
     }
   }
   }
@@ -1122,7 +1153,7 @@ public final class TextFormat {
    * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
    * 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.
    * 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));
     return escapeBytes(ByteString.copyFromUtf8(input));
   }
   }
 
 
@@ -1130,17 +1161,18 @@ public final class TextFormat {
    * Un-escape a text string as escaped using {@link #escapeText(String)}.
    * Un-escape a text string as escaped using {@link #escapeText(String)}.
    * Two-digit hex escapes (starting with "\x") are also recognized.
    * 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();
     return unescapeBytes(input).toStringUtf8();
   }
   }
 
 
   /** Is this an octal digit? */
   /** Is this an octal digit? */
-  private static boolean isOctal(char c) {
+  private static boolean isOctal(final char c) {
     return '0' <= c && c <= '7';
     return '0' <= c && c <= '7';
   }
   }
 
 
   /** Is this a hex digit? */
   /** Is this a hex digit? */
-  private static boolean isHex(char c) {
+  private static boolean isHex(final char c) {
     return ('0' <= c && c <= '9') ||
     return ('0' <= c && c <= '9') ||
            ('a' <= c && c <= 'f') ||
            ('a' <= c && c <= 'f') ||
            ('A' <= c && c <= 'F');
            ('A' <= c && c <= 'F');
@@ -1151,7 +1183,7 @@ public final class TextFormat {
    * numeric value.  This is like {@code Character.digit()} but we don't accept
    * numeric value.  This is like {@code Character.digit()} but we don't accept
    * non-ASCII digits.
    * non-ASCII digits.
    */
    */
-  private static int digitValue(char c) {
+  private static int digitValue(final char c) {
     if ('0' <= c && c <= '9') {
     if ('0' <= c && c <= '9') {
       return c - '0';
       return c - '0';
     } else if ('a' <= c && c <= 'z') {
     } else if ('a' <= c && c <= 'z') {
@@ -1166,7 +1198,7 @@ public final class TextFormat {
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
    * and "0" to signify hexidecimal and octal numbers, respectively.
    * 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);
     return (int) parseInteger(text, true, false);
   }
   }
 
 
@@ -1177,7 +1209,7 @@ public final class TextFormat {
    * result is coerced to a (signed) {@code int} when returned since Java has
    * result is coerced to a (signed) {@code int} when returned since Java has
    * no unsigned integer type.
    * 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);
     return (int) parseInteger(text, false, false);
   }
   }
 
 
@@ -1186,7 +1218,7 @@ public final class TextFormat {
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
    * and "0" to signify hexidecimal and octal numbers, respectively.
    * 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);
     return parseInteger(text, true, true);
   }
   }
 
 
@@ -1197,13 +1229,13 @@ public final class TextFormat {
    * result is coerced to a (signed) {@code long} when returned since Java has
    * result is coerced to a (signed) {@code long} when returned since Java has
    * no unsigned long type.
    * no unsigned long type.
    */
    */
-  static long parseUInt64(String text) throws NumberFormatException {
+  static long parseUInt64(final String text) throws NumberFormatException {
     return parseInteger(text, false, true);
     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 {
                                    throws NumberFormatException {
     int pos = 0;
     int pos = 0;
 
 
@@ -1224,7 +1256,7 @@ public final class TextFormat {
       radix = 8;
       radix = 8;
     }
     }
 
 
-    String numberText = text.substring(pos);
+    final String numberText = text.substring(pos);
 
 
     long result = 0;
     long result = 0;
     if (numberText.length() < 16) {
     if (numberText.length() < 16) {

+ 12 - 73
java/src/main/java/com/google/protobuf/UninitializedMessageException.java

@@ -30,12 +30,8 @@
 
 
 package com.google.protobuf;
 package com.google.protobuf;
 
 
-import com.google.protobuf.Descriptors.FieldDescriptor;
-
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Collections;
 import java.util.List;
 import java.util.List;
-import java.util.Map;
 
 
 /**
 /**
  * Thrown when attempting to build a protocol message that is missing required
  * Thrown when attempting to build a protocol message that is missing required
@@ -51,11 +47,15 @@ import java.util.Map;
  * @author kenton@google.com Kenton Varda
  * @author kenton@google.com Kenton Varda
  */
  */
 public class UninitializedMessageException extends RuntimeException {
 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));
     super(buildDescription(missingFields));
     this.missingFields = missingFields;
     this.missingFields = missingFields;
   }
   }
@@ -65,6 +65,8 @@ public class UninitializedMessageException extends RuntimeException {
   /**
   /**
    * Get a list of human-readable names of required fields missing from this
    * 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".
    * 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() {
   public List<String> getMissingFields() {
     return Collections.unmodifiableList(missingFields);
     return Collections.unmodifiableList(missingFields);
@@ -80,11 +82,11 @@ public class UninitializedMessageException extends RuntimeException {
   }
   }
 
 
   /** Construct the description string for this exception. */
   /** 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: ");
       new StringBuilder("Message missing required fields: ");
     boolean first = true;
     boolean first = true;
-    for (String field : missingFields) {
+    for (final String field : missingFields) {
       if (first) {
       if (first) {
         first = false;
         first = false;
       } else {
       } else {
@@ -94,67 +96,4 @@ public class UninitializedMessageException extends RuntimeException {
     }
     }
     return description.toString();
     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();
-  }
 }
 }

+ 274 - 115
java/src/main/java/com/google/protobuf/UnknownFieldSet.java

@@ -30,15 +30,17 @@
 
 
 package com.google.protobuf;
 package com.google.protobuf;
 
 
-import java.io.InputStream;
+import com.google.protobuf.Internal.ThreadLocalQuickQueue;
+
 import java.io.IOException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Collections;
-import java.util.TreeMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.TreeMap;
 
 
 /**
 /**
  * {@code UnknownFieldSet} is used to keep track of fields which were seen when
  * {@code UnknownFieldSet} is used to keep track of fields which were seen when
@@ -48,56 +50,59 @@ import java.util.Map;
  * compiled before the new types were added.
  * compiled before the new types were added.
  *
  *
  * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
  * <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.
  * <p>Most users will never need to use this class.
  *
  *
  * @author kenton@google.com Kenton Varda
  * @author kenton@google.com Kenton Varda
  */
  */
-public final class UnknownFieldSet {
+public final class UnknownFieldSet implements MessageLite {
   private UnknownFieldSet() {}
   private UnknownFieldSet() {}
 
 
-  /** Create a new {@link UnknownFieldSet.Builder}. */
+  /** Create a new {@link Builder}. */
   public static Builder newBuilder() {
   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}.
    * 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}. */
   /** Get an empty {@code UnknownFieldSet}. */
   public static UnknownFieldSet getDefaultInstance() {
   public static UnknownFieldSet getDefaultInstance() {
     return defaultInstance;
     return defaultInstance;
   }
   }
-  private static UnknownFieldSet defaultInstance =
+  public UnknownFieldSet getDefaultInstanceForType() {
+    return defaultInstance;
+  }
+  private static final UnknownFieldSet defaultInstance =
     new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
     new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
 
 
   /**
   /**
    * Construct an {@code UnknownFieldSet} around the given map.  The map is
    * Construct an {@code UnknownFieldSet} around the given map.  The map is
    * expected to be immutable.
    * expected to be immutable.
    */
    */
-  private UnknownFieldSet(Map<Integer, Field> fields) {
+  private UnknownFieldSet(final Map<Integer, Field> fields) {
     this.fields = fields;
     this.fields = fields;
   }
   }
   private Map<Integer, Field> fields;
   private Map<Integer, Field> fields;
 
 
   @Override
   @Override
-  public boolean equals(Object other) {
+  public boolean equals(final Object other) {
     if (this == other) {
     if (this == other) {
       return true;
       return true;
     }
     }
     return (other instanceof UnknownFieldSet) &&
     return (other instanceof UnknownFieldSet) &&
-        this.fields.equals(((UnknownFieldSet) other).fields);
+           fields.equals(((UnknownFieldSet) other).fields);
   }
   }
 
 
   @Override
   @Override
   public int hashCode() {
   public int hashCode() {
-    return this.fields.hashCode();
+    return fields.hashCode();
   }
   }
 
 
   /** Get a map of fields in the set by number. */
   /** Get a map of fields in the set by number. */
@@ -106,7 +111,7 @@ public final class UnknownFieldSet {
   }
   }
 
 
   /** Check if the given field number is present in the set. */
   /** 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);
     return fields.containsKey(number);
   }
   }
 
 
@@ -114,14 +119,14 @@ public final class UnknownFieldSet {
    * Get a field by number.  Returns an empty field if not present.  Never
    * Get a field by number.  Returns an empty field if not present.  Never
    * returns {@code null}.
    * 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;
     return (result == null) ? Field.getDefaultInstance() : result;
   }
   }
 
 
   /** Serializes the set and writes it to {@code output}. */
   /** 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);
       entry.getValue().writeTo(entry.getKey(), output);
     }
     }
   }
   }
@@ -131,7 +136,8 @@ public final class UnknownFieldSet {
    * just a trivial wrapper around
    * just a trivial wrapper around
    * {@link TextFormat#printToString(UnknownFieldSet)}.
    * {@link TextFormat#printToString(UnknownFieldSet)}.
    */
    */
-  public final String toString() {
+  @Override
+  public String toString() {
     return TextFormat.printToString(this);
     return TextFormat.printToString(this);
   }
   }
 
 
@@ -139,13 +145,13 @@ public final class UnknownFieldSet {
    * Serializes the message to a {@code ByteString} and returns it. This is
    * Serializes the message to a {@code ByteString} and returns it. This is
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
    */
-  public final ByteString toByteString() {
+  public ByteString toByteString() {
     try {
     try {
-      ByteString.CodedBuilder out =
+      final ByteString.CodedBuilder out =
         ByteString.newCodedBuilder(getSerializedSize());
         ByteString.newCodedBuilder(getSerializedSize());
       writeTo(out.getCodedOutput());
       writeTo(out.getCodedOutput());
       return out.build();
       return out.build();
-    } catch (IOException e) {
+    } catch (final IOException e) {
       throw new RuntimeException(
       throw new RuntimeException(
         "Serializing to a ByteString threw an IOException (should " +
         "Serializing to a ByteString threw an IOException (should " +
         "never happen).", e);
         "never happen).", e);
@@ -156,14 +162,14 @@ public final class UnknownFieldSet {
    * Serializes the message to a {@code byte} array and returns it.  This is
    * Serializes the message to a {@code byte} array and returns it.  This is
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
    */
-  public final byte[] toByteArray() {
+  public byte[] toByteArray() {
     try {
     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);
       writeTo(output);
       output.checkNoSpaceLeft();
       output.checkNoSpaceLeft();
       return result;
       return result;
-    } catch (IOException e) {
+    } catch (final IOException e) {
       throw new RuntimeException(
       throw new RuntimeException(
         "Serializing to a byte array threw an IOException " +
         "Serializing to a byte array threw an IOException " +
         "(should never happen).", e);
         "(should never happen).", e);
@@ -174,8 +180,15 @@ public final class UnknownFieldSet {
    * Serializes the message and writes it to {@code output}.  This is just a
    * Serializes the message and writes it to {@code output}.  This is just a
    * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    * 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);
     writeTo(codedOutput);
     codedOutput.flush();
     codedOutput.flush();
   }
   }
@@ -183,7 +196,7 @@ public final class UnknownFieldSet {
   /** Get the number of bytes required to encode this set. */
   /** Get the number of bytes required to encode this set. */
   public int getSerializedSize() {
   public int getSerializedSize() {
     int result = 0;
     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());
       result += entry.getValue().getSerializedSize(entry.getKey());
     }
     }
     return result;
     return result;
@@ -193,9 +206,9 @@ public final class UnknownFieldSet {
    * Serializes the set and writes it to {@code output} using
    * Serializes the set and writes it to {@code output} using
    * {@code MessageSet} wire format.
    * {@code MessageSet} wire format.
    */
    */
-  public void writeAsMessageSetTo(CodedOutputStream output)
+  public void writeAsMessageSetTo(final CodedOutputStream output)
       throws IOException {
       throws IOException {
-    for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       entry.getValue().writeAsMessageSetExtensionTo(
       entry.getValue().writeAsMessageSetExtensionTo(
         entry.getKey(), output);
         entry.getKey(), output);
     }
     }
@@ -207,37 +220,51 @@ public final class UnknownFieldSet {
    */
    */
   public int getSerializedSizeAsMessageSet() {
   public int getSerializedSizeAsMessageSet() {
     int result = 0;
     int result = 0;
-    for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       result += entry.getValue().getSerializedSizeAsMessageSetExtension(
       result += entry.getValue().getSerializedSizeAsMessageSetExtension(
         entry.getKey());
         entry.getKey());
     }
     }
     return result;
     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. */
   /** Parse an {@code UnknownFieldSet} from the given input stream. */
-  static public UnknownFieldSet parseFrom(CodedInputStream input)
+  public static UnknownFieldSet parseFrom(final CodedInputStream input)
                                           throws IOException {
                                           throws IOException {
     return newBuilder().mergeFrom(input).build();
     return newBuilder().mergeFrom(input).build();
   }
   }
 
 
   /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
   /** 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 {
       throws InvalidProtocolBufferException {
     return newBuilder().mergeFrom(data).build();
     return newBuilder().mergeFrom(data).build();
   }
   }
 
 
   /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
   /** 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 {
       throws InvalidProtocolBufferException {
     return newBuilder().mergeFrom(data).build();
     return newBuilder().mergeFrom(data).build();
   }
   }
 
 
   /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
   /** 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 {
                                           throws IOException {
     return newBuilder().mergeFrom(input).build();
     return newBuilder().mergeFrom(input).build();
   }
   }
 
 
+  public Builder newBuilderForType() {
+    return newBuilder();
+  }
+
+  public Builder toBuilder() {
+    return newBuilder().mergeFrom(this);
+  }
+
   /**
   /**
    * Builder for {@link UnknownFieldSet}s.
    * Builder for {@link UnknownFieldSet}s.
    *
    *
@@ -250,21 +277,35 @@ public final class UnknownFieldSet {
    *
    *
    * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
    * <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 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
     // 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
     //   modified so that we can efficiently add to it multiple times in a
     //   row (important when parsing an unknown repeated field).
     //   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
      * Get a field builder for the given field number which includes any
      * values that already exist.
      * values that already exist.
      */
      */
-    private Field.Builder getFieldBuilder(int number) {
+    private Field.Builder getFieldBuilder(final int number) {
       if (lastField != null) {
       if (lastField != null) {
         if (number == lastFieldNumber) {
         if (number == lastFieldNumber) {
           return lastField;
           return lastField;
@@ -275,7 +316,7 @@ public final class UnknownFieldSet {
       if (number == 0) {
       if (number == 0) {
         return null;
         return null;
       } else {
       } else {
-        Field existing = fields.get(number);
+        final Field existing = fields.get(number);
         lastFieldNumber = number;
         lastFieldNumber = number;
         lastField = Field.newBuilder();
         lastField = Field.newBuilder();
         if (existing != null) {
         if (existing != null) {
@@ -289,26 +330,48 @@ public final class UnknownFieldSet {
      * Build the {@link UnknownFieldSet} and return it.
      * Build the {@link UnknownFieldSet} and return it.
      *
      *
      * <p>Once {@code build()} has been called, the {@code Builder} will no
      * <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() {
     public UnknownFieldSet build() {
       getFieldBuilder(0);  // Force lastField to be built.
       getFieldBuilder(0);  // Force lastField to be built.
-      UnknownFieldSet result;
+      final UnknownFieldSet result;
       if (fields.isEmpty()) {
       if (fields.isEmpty()) {
         result = getDefaultInstance();
         result = getDefaultInstance();
       } else {
       } else {
         result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
         result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
       }
       }
       fields = null;
       fields = null;
+      builders.get().offer(this);
       return result;
       return result;
     }
     }
 
 
-    /** Reset the builder to an empty set. */
-    public Builder clear() {
-      fields = new TreeMap<Integer, Field>();
+    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;
       lastFieldNumber = 0;
       lastField = null;
       lastField = null;
+    }
+
+    /** Reset the builder to an empty set. */
+    public Builder clear() {
+      reinitialize();
       return this;
       return this;
     }
     }
 
 
@@ -317,9 +380,9 @@ public final class UnknownFieldSet {
      * exists in both sets, {@code other}'s values for that field will be
      * exists in both sets, {@code other}'s values for that field will be
      * appended to the values in this set.
      * appended to the values in this set.
      */
      */
-    public Builder mergeFrom(UnknownFieldSet other) {
+    public Builder mergeFrom(final UnknownFieldSet other) {
       if (other != getDefaultInstance()) {
       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());
           mergeField(entry.getKey(), entry.getValue());
         }
         }
       }
       }
@@ -330,7 +393,7 @@ public final class UnknownFieldSet {
      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
      * number already exists, the two are merged.
      * 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) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
       }
@@ -350,7 +413,7 @@ public final class UnknownFieldSet {
      * value.  This is used in particular when an unknown enum value is
      * value.  This is used in particular when an unknown enum value is
      * encountered.
      * encountered.
      */
      */
-    public Builder mergeVarintField(int number, int value) {
+    public Builder mergeVarintField(final int number, final int value) {
       if (number == 0) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
       }
@@ -359,7 +422,7 @@ public final class UnknownFieldSet {
     }
     }
 
 
     /** Check if the given field number is present in the set. */
     /** 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) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
       }
@@ -370,7 +433,7 @@ public final class UnknownFieldSet {
      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
      * number already exists, it is removed.
      * 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) {
       if (number == 0) {
         throw new IllegalArgumentException("Zero is not a valid field number.");
         throw new IllegalArgumentException("Zero is not a valid field number.");
       }
       }
@@ -379,6 +442,9 @@ public final class UnknownFieldSet {
         lastField = null;
         lastField = null;
         lastFieldNumber = 0;
         lastFieldNumber = 0;
       }
       }
+      if (fields.isEmpty()) {
+        fields = new TreeMap<Integer,Field>();
+      }
       fields.put(number, field);
       fields.put(number, field);
       return this;
       return this;
     }
     }
@@ -396,9 +462,9 @@ public final class UnknownFieldSet {
      * Parse an entire message from {@code input} and merge its fields into
      * Parse an entire message from {@code input} and merge its fields into
      * this set.
      * this set.
      */
      */
-    public Builder mergeFrom(CodedInputStream input) throws IOException {
+    public Builder mergeFrom(final CodedInputStream input) throws IOException {
       while (true) {
       while (true) {
-        int tag = input.readTag();
+        final int tag = input.readTag();
         if (tag == 0 || !mergeFieldFrom(tag, input)) {
         if (tag == 0 || !mergeFieldFrom(tag, input)) {
           break;
           break;
         }
         }
@@ -411,9 +477,9 @@ public final class UnknownFieldSet {
      * @param tag The field's tag number, which was already parsed.
      * @param tag The field's tag number, which was already parsed.
      * @return {@code false} if the tag is an engroup tag.
      * @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 {
                                   throws IOException {
-      int number = WireFormat.getTagFieldNumber(tag);
+      final int number = WireFormat.getTagFieldNumber(tag);
       switch (WireFormat.getTagWireType(tag)) {
       switch (WireFormat.getTagWireType(tag)) {
         case WireFormat.WIRETYPE_VARINT:
         case WireFormat.WIRETYPE_VARINT:
           getFieldBuilder(number).addVarint(input.readInt64());
           getFieldBuilder(number).addVarint(input.readInt64());
@@ -424,12 +490,12 @@ public final class UnknownFieldSet {
         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
           getFieldBuilder(number).addLengthDelimited(input.readBytes());
           getFieldBuilder(number).addLengthDelimited(input.readBytes());
           return true;
           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());
           getFieldBuilder(number).addGroup(subBuilder.build());
           return true;
           return true;
-        }
         case WireFormat.WIRETYPE_END_GROUP:
         case WireFormat.WIRETYPE_END_GROUP:
           return false;
           return false;
         case WireFormat.WIRETYPE_FIXED32:
         case WireFormat.WIRETYPE_FIXED32:
@@ -445,16 +511,16 @@ public final class UnknownFieldSet {
      * set being built.  This is just a small wrapper around
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      * {@link #mergeFrom(CodedInputStream)}.
      */
      */
-    public Builder mergeFrom(ByteString data)
+    public Builder mergeFrom(final ByteString data)
         throws InvalidProtocolBufferException {
         throws InvalidProtocolBufferException {
       try {
       try {
-        CodedInputStream input = data.newCodedInput();
+        final CodedInputStream input = data.newCodedInput();
         mergeFrom(input);
         mergeFrom(input);
         input.checkLastTagWas(0);
         input.checkLastTagWas(0);
         return this;
         return this;
-      } catch (InvalidProtocolBufferException e) {
+      } catch (final InvalidProtocolBufferException e) {
         throw e;
         throw e;
-      } catch (IOException e) {
+      } catch (final IOException e) {
         throw new RuntimeException(
         throw new RuntimeException(
           "Reading from a ByteString threw an IOException (should " +
           "Reading from a ByteString threw an IOException (should " +
           "never happen).", e);
           "never happen).", e);
@@ -466,16 +532,16 @@ public final class UnknownFieldSet {
      * set being built.  This is just a small wrapper around
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      * {@link #mergeFrom(CodedInputStream)}.
      */
      */
-    public Builder mergeFrom(byte[] data)
+    public Builder mergeFrom(final byte[] data)
         throws InvalidProtocolBufferException {
         throws InvalidProtocolBufferException {
       try {
       try {
-        CodedInputStream input = CodedInputStream.newInstance(data);
+        final CodedInputStream input = CodedInputStream.newInstance(data);
         mergeFrom(input);
         mergeFrom(input);
         input.checkLastTagWas(0);
         input.checkLastTagWas(0);
         return this;
         return this;
-      } catch (InvalidProtocolBufferException e) {
+      } catch (final InvalidProtocolBufferException e) {
         throw e;
         throw e;
-      } catch (IOException e) {
+      } catch (final IOException e) {
         throw new RuntimeException(
         throw new RuntimeException(
           "Reading from a byte array threw an IOException (should " +
           "Reading from a byte array threw an IOException (should " +
           "never happen).", e);
           "never happen).", e);
@@ -487,12 +553,88 @@ public final class UnknownFieldSet {
      * set being built.  This is just a small wrapper around
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      * {@link #mergeFrom(CodedInputStream)}.
      */
      */
-    public Builder mergeFrom(InputStream input) throws IOException {
-      CodedInputStream codedInput = CodedInputStream.newInstance(input);
+    public Builder mergeFrom(final InputStream input) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
       mergeFrom(codedInput);
       mergeFrom(codedInput);
       codedInput.checkLastTagWas(0);
       codedInput.checkLastTagWas(0);
       return this;
       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;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    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 @@ public final class UnknownFieldSet {
    * wire types.
    * wire types.
    *
    *
    * <p>{@code Field} is an immutable class.  To construct one, you must use a
    * <p>{@code Field} is an immutable class.  To construct one, you must use a
-   * {@link Field.Builder}.
+   * {@link Builder}.
    *
    *
    * @see UnknownFieldSet
    * @see UnknownFieldSet
    */
    */
@@ -519,22 +661,22 @@ public final class UnknownFieldSet {
 
 
     /** Construct a new {@link Builder}. */
     /** Construct a new {@link Builder}. */
     public static Builder newBuilder() {
     public static Builder newBuilder() {
-      return new Builder();
+      return Builder.create();
     }
     }
 
 
     /**
     /**
      * Construct a new {@link Builder} and initialize it to a copy of
      * Construct a new {@link Builder} and initialize it to a copy of
      * {@code copyFrom}.
      * {@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}. */
     /** Get an empty {@code Field}. */
     public static Field getDefaultInstance() {
     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. */
     /** Get the list of varint values for this field. */
     public List<Long> getVarintList()               { return varint;          }
     public List<Long> getVarintList()               { return varint;          }
@@ -556,14 +698,14 @@ public final class UnknownFieldSet {
     public List<UnknownFieldSet> getGroupList()      { return group;           }
     public List<UnknownFieldSet> getGroupList()      { return group;           }
 
 
     @Override
     @Override
-    public boolean equals(Object other) {
+    public boolean equals(final Object other) {
       if (this == other) {
       if (this == other) {
         return true;
         return true;
       }
       }
       if (!(other instanceof Field)) {
       if (!(other instanceof Field)) {
         return false;
         return false;
       }
       }
-      return Arrays.equals(this.getIdentityArray(),
+      return Arrays.equals(getIdentityArray(),
           ((Field) other).getIdentityArray());
           ((Field) other).getIdentityArray());
     }
     }
 
 
@@ -574,37 +716,37 @@ public final class UnknownFieldSet {
 
 
     /**
     /**
      * Returns the array of objects to be used to uniquely identify this
      * Returns the array of objects to be used to uniquely identify this
-     * {@link UnknownFieldSet.Field} instance.
+     * {@link Field} instance.
      */
      */
     private Object[] getIdentityArray() {
     private Object[] getIdentityArray() {
       return new Object[] {
       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
      * Serializes the field, including field number, and writes it to
      * {@code output}.
      * {@code output}.
      */
      */
-    public void writeTo(int fieldNumber, CodedOutputStream output)
+    public void writeTo(final int fieldNumber, final CodedOutputStream output)
                         throws IOException {
                         throws IOException {
-      for (long value : varint) {
+      for (final long value : varint) {
         output.writeUInt64(fieldNumber, value);
         output.writeUInt64(fieldNumber, value);
       }
       }
-      for (int value : fixed32) {
+      for (final int value : fixed32) {
         output.writeFixed32(fieldNumber, value);
         output.writeFixed32(fieldNumber, value);
       }
       }
-      for (long value : fixed64) {
+      for (final long value : fixed64) {
         output.writeFixed64(fieldNumber, value);
         output.writeFixed64(fieldNumber, value);
       }
       }
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         output.writeBytes(fieldNumber, value);
         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 @@ public final class UnknownFieldSet {
      * Get the number of bytes required to encode this field, including field
      * Get the number of bytes required to encode this field, including field
      * number.
      * number.
      */
      */
-    public int getSerializedSize(int fieldNumber) {
+    public int getSerializedSize(final int fieldNumber) {
       int result = 0;
       int result = 0;
-      for (long value : varint) {
+      for (final long value : varint) {
         result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
         result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
       }
       }
-      for (int value : fixed32) {
+      for (final int value : fixed32) {
         result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
         result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
       }
       }
-      for (long value : fixed64) {
+      for (final long value : fixed64) {
         result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
         result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
       }
       }
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         result += CodedOutputStream.computeBytesSize(fieldNumber, value);
         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;
       return result;
     }
     }
@@ -637,10 +779,10 @@ public final class UnknownFieldSet {
      * {@code output}, using {@code MessageSet} wire format.
      * {@code output}, using {@code MessageSet} wire format.
      */
      */
     public void writeAsMessageSetExtensionTo(
     public void writeAsMessageSetExtensionTo(
-        int fieldNumber,
-        CodedOutputStream output)
+        final int fieldNumber,
+        final CodedOutputStream output)
         throws IOException {
         throws IOException {
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         output.writeRawMessageSetExtension(fieldNumber, value);
         output.writeRawMessageSetExtension(fieldNumber, value);
       }
       }
     }
     }
@@ -649,9 +791,9 @@ public final class UnknownFieldSet {
      * Get the number of bytes required to encode this field, including field
      * Get the number of bytes required to encode this field, including field
      * number, using {@code MessageSet} wire format.
      * number, using {@code MessageSet} wire format.
      */
      */
-    public int getSerializedSizeAsMessageSetExtension(int fieldNumber) {
+    public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
       int result = 0;
       int result = 0;
-      for (ByteString value : lengthDelimited) {
+      for (final ByteString value : lengthDelimited) {
         result += CodedOutputStream.computeRawMessageSetExtensionSize(
         result += CodedOutputStream.computeRawMessageSetExtensionSize(
           fieldNumber, value);
           fieldNumber, value);
       }
       }
@@ -670,13 +812,29 @@ public final class UnknownFieldSet {
      * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
      * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
      */
      */
     public static final class 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 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
        * Build the field.  After {@code build()} has been called, the
        * {@code Builder} is no longer usable.  Calling any other method will
        * {@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() {
       public Field build() {
         if (result.varint == null) {
         if (result.varint == null) {
@@ -706,8 +864,9 @@ public final class UnknownFieldSet {
           result.group = Collections.unmodifiableList(result.group);
           result.group = Collections.unmodifiableList(result.group);
         }
         }
 
 
-        Field returnMe = result;
+        final Field returnMe = result;
         result = null;
         result = null;
+        builders.get().offer(this);
         return returnMe;
         return returnMe;
       }
       }
 
 
@@ -722,7 +881,7 @@ public final class UnknownFieldSet {
        * of values, {@code other}'s values are append to the ones in this
        * of values, {@code other}'s values are append to the ones in this
        * field.
        * field.
        */
        */
-      public Builder mergeFrom(Field other) {
+      public Builder mergeFrom(final Field other) {
         if (!other.varint.isEmpty()) {
         if (!other.varint.isEmpty()) {
           if (result.varint == null) {
           if (result.varint == null) {
             result.varint = new ArrayList<Long>();
             result.varint = new ArrayList<Long>();
@@ -757,7 +916,7 @@ public final class UnknownFieldSet {
       }
       }
 
 
       /** Add a varint value. */
       /** Add a varint value. */
-      public Builder addVarint(long value) {
+      public Builder addVarint(final long value) {
         if (result.varint == null) {
         if (result.varint == null) {
           result.varint = new ArrayList<Long>();
           result.varint = new ArrayList<Long>();
         }
         }
@@ -766,7 +925,7 @@ public final class UnknownFieldSet {
       }
       }
 
 
       /** Add a fixed32 value. */
       /** Add a fixed32 value. */
-      public Builder addFixed32(int value) {
+      public Builder addFixed32(final int value) {
         if (result.fixed32 == null) {
         if (result.fixed32 == null) {
           result.fixed32 = new ArrayList<Integer>();
           result.fixed32 = new ArrayList<Integer>();
         }
         }
@@ -775,7 +934,7 @@ public final class UnknownFieldSet {
       }
       }
 
 
       /** Add a fixed64 value. */
       /** Add a fixed64 value. */
-      public Builder addFixed64(long value) {
+      public Builder addFixed64(final long value) {
         if (result.fixed64 == null) {
         if (result.fixed64 == null) {
           result.fixed64 = new ArrayList<Long>();
           result.fixed64 = new ArrayList<Long>();
         }
         }
@@ -784,7 +943,7 @@ public final class UnknownFieldSet {
       }
       }
 
 
       /** Add a length-delimited value. */
       /** Add a length-delimited value. */
-      public Builder addLengthDelimited(ByteString value) {
+      public Builder addLengthDelimited(final ByteString value) {
         if (result.lengthDelimited == null) {
         if (result.lengthDelimited == null) {
           result.lengthDelimited = new ArrayList<ByteString>();
           result.lengthDelimited = new ArrayList<ByteString>();
         }
         }
@@ -793,7 +952,7 @@ public final class UnknownFieldSet {
       }
       }
 
 
       /** Add an embedded group. */
       /** Add an embedded group. */
-      public Builder addGroup(UnknownFieldSet value) {
+      public Builder addGroup(final UnknownFieldSet value) {
         if (result.group == null) {
         if (result.group == null) {
           result.group = new ArrayList<UnknownFieldSet>();
           result.group = new ArrayList<UnknownFieldSet>();
         }
         }

+ 62 - 32
java/src/main/java/com/google/protobuf/WireFormat.java

@@ -56,54 +56,84 @@ public final class WireFormat {
   static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
   static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
 
 
   /** Given a tag value, determines the wire type (the lower 3 bits). */
   /** 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;
     return tag & TAG_TYPE_MASK;
   }
   }
 
 
   /** Given a tag value, determines the field number (the upper 29 bits). */
   /** 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;
     return tag >>> TAG_TYPE_BITS;
   }
   }
 
 
   /** Makes a tag value given a field number and wire type. */
   /** 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;
     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;
+    }
+
+    /**
+     * The default default value for fields of this type, if it's a primitive
+     * type.
+     */
+    Object getDefaultDefault() {
+      return defaultDefault;
     }
     }
 
 
-    throw new RuntimeException(
-      "There is no way to get here, but the compiler thinks otherwise.");
+    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.
   // Field numbers for feilds in MessageSet wire format.

+ 30 - 0
java/src/test/java/com/google/protobuf/DescriptorsTest.java

@@ -367,4 +367,34 @@ public class DescriptorsTest extends TestCase {
     assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
     assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
       method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
       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());
+    }
+  }
 }
 }

+ 12 - 0
java/src/test/java/com/google/protobuf/DynamicMessageTest.java

@@ -73,6 +73,18 @@ public class DynamicMessageTest extends TestCase {
     }
     }
   }
   }
 
 
+  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 {
   public void testDynamicMessageSettersRejectNull() throws Exception {
     Message.Builder builder =
     Message.Builder builder =
       DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
       DynamicMessage.newBuilder(TestAllTypes.getDescriptor());

+ 89 - 0
java/src/test/java/com/google/protobuf/GeneratedMessageTest.java

@@ -43,6 +43,8 @@ import protobuf_unittest.MultipleFilesTestProto;
 import protobuf_unittest.MessageWithNoOuter;
 import protobuf_unittest.MessageWithNoOuter;
 import protobuf_unittest.EnumWithNoOuter;
 import protobuf_unittest.EnumWithNoOuter;
 import protobuf_unittest.ServiceWithNoOuter;
 import protobuf_unittest.ServiceWithNoOuter;
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 
 
 import junit.framework.TestCase;
 import junit.framework.TestCase;
 import java.util.Arrays;
 import java.util.Arrays;
@@ -82,6 +84,17 @@ public class GeneratedMessageTest extends TestCase {
     }
     }
   }
   }
 
 
+  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 {
   public void testSettersRejectNull() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     try {
     try {
@@ -338,6 +351,16 @@ public class GeneratedMessageTest extends TestCase {
         instanceof ProtocolMessageEnum);
         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.
   // Extensions.
 
 
@@ -420,6 +443,12 @@ public class GeneratedMessageTest extends TestCase {
         .getExtensionCount(UnittestProto.repeatedInt32Extension));
         .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 {
   public void testExtensionMergeFrom() throws Exception {
     TestAllExtensions original =
     TestAllExtensions original =
       TestAllExtensions.newBuilder()
       TestAllExtensions.newBuilder()
@@ -431,6 +460,66 @@ public class GeneratedMessageTest extends TestCase {
         1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
         1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
   }
   }
 
 
+  // =================================================================
+  // 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
   // multiple_files_test
 
 

+ 114 - 0
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());
+  }
+}

+ 945 - 86
java/src/test/java/com/google/protobuf/TestUtil.java

@@ -31,6 +31,7 @@
 package com.google.protobuf;
 package com.google.protobuf;
 
 
 import protobuf_unittest.UnittestProto;
 import protobuf_unittest.UnittestProto;
+import com.google.protobuf.UnittestLite;
 
 
 // The static imports are to avoid 100+ char lines.  The following is roughly equivalent to
 // The static imports are to avoid 100+ char lines.  The following is roughly equivalent to
 // import static protobuf_unittest.UnittestProto.*;
 // import static protobuf_unittest.UnittestProto.*;
@@ -123,6 +124,95 @@ import static protobuf_unittest.UnittestProto.packedDoubleExtension;
 import static protobuf_unittest.UnittestProto.packedBoolExtension;
 import static protobuf_unittest.UnittestProto.packedBoolExtension;
 import static protobuf_unittest.UnittestProto.packedEnumExtension;
 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.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestPackedExtensions;
 import protobuf_unittest.UnittestProto.TestPackedExtensions;
@@ -132,6 +222,14 @@ import protobuf_unittest.UnittestProto.ForeignEnum;
 import com.google.protobuf.test.UnittestImport.ImportMessage;
 import com.google.protobuf.test.UnittestImport.ImportMessage;
 import com.google.protobuf.test.UnittestImport.ImportEnum;
 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 junit.framework.Assert;
 
 
 import java.io.File;
 import java.io.File;
@@ -179,6 +277,12 @@ class TestUtil {
     return builder.build();
     return builder.build();
   }
   }
 
 
+  public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    setAllExtensions(builder);
+    return builder.build();
+  }
+
   public static TestPackedTypes getPackedSet() {
   public static TestPackedTypes getPackedSet() {
     TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
     TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
     setPackedFields(builder);
     setPackedFields(builder);
@@ -191,6 +295,13 @@ class TestUtil {
     return builder.build();
     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
    * Set every field of {@code message} to the values expected by
    * {@code assertAllFieldsSet()}.
    * {@code assertAllFieldsSet()}.
@@ -809,6 +920,90 @@ class TestUtil {
     Assert.assertEquals("525", message.getRepeatedCord(1));
     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
   // Like above, but for extensions
 
 
@@ -846,6 +1041,18 @@ class TestUtil {
   private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
   private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
     Assert.assertEquals(a, 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
    * Get an unmodifiable {@link ExtensionRegistry} containing all the
@@ -857,12 +1064,23 @@ class TestUtil {
     return registry.getUnmodifiable();
     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}.
    * given {@link ExtensionRegistry}.
    */
    */
   public static void registerAllExtensions(ExtensionRegistry registry) {
   public static void registerAllExtensions(ExtensionRegistry registry) {
     UnittestProto.registerAllExtensions(registry);
     UnittestProto.registerAllExtensions(registry);
+    registerAllExtensionsLite(registry);
+  }
+
+  public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+    UnittestLite.registerAllExtensions(registry);
   }
   }
 
 
   /**
   /**
@@ -1509,90 +1727,6 @@ class TestUtil {
     assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
     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) {
   public static void setPackedExtensions(TestPackedExtensions.Builder message) {
     message.addExtension(packedInt32Extension   , 601);
     message.addExtension(packedInt32Extension   , 601);
     message.addExtension(packedInt64Extension   , 602L);
     message.addExtension(packedInt64Extension   , 602L);
@@ -1672,8 +1806,733 @@ class TestUtil {
                           message.getExtension(packedEnumExtension, 1));
                           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
    * Performs the same things that the methods of {@code TestUtil} do, but

+ 22 - 3
java/src/test/java/com/google/protobuf/TextFormatTest.java

@@ -30,9 +30,12 @@
 
 
 package com.google.protobuf;
 package com.google.protobuf;
 
 
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestProto.OneString;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestEmptyMessage;
 import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
 import protobuf_unittest.UnittestMset.TestMessageSet;
 import protobuf_unittest.UnittestMset.TestMessageSet;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
@@ -173,6 +176,22 @@ public class TextFormatTest extends TestCase {
       TextFormat.printToString(message));
       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
    * Helper to construct a ByteString from a String containing only 8-bit
    * characters.  The characters are converted directly to bytes, *not*
    * characters.  The characters are converted directly to bytes, *not*
@@ -450,21 +469,21 @@ public class TextFormatTest extends TestCase {
     try {
     try {
       TextFormat.unescapeText("\\x");
       TextFormat.unescapeText("\\x");
       fail("Should have thrown an exception.");
       fail("Should have thrown an exception.");
-    } catch (TextFormat.InvalidEscapeSequence e) {
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
       // success
     }
     }
 
 
     try {
     try {
       TextFormat.unescapeText("\\z");
       TextFormat.unescapeText("\\z");
       fail("Should have thrown an exception.");
       fail("Should have thrown an exception.");
-    } catch (TextFormat.InvalidEscapeSequence e) {
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
       // success
     }
     }
 
 
     try {
     try {
       TextFormat.unescapeText("\\");
       TextFormat.unescapeText("\\");
       fail("Should have thrown an exception.");
       fail("Should have thrown an exception.");
-    } catch (TextFormat.InvalidEscapeSequence e) {
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
       // success
     }
     }
   }
   }

+ 65 - 0
java/src/test/java/com/google/protobuf/WireFormatTest.java

@@ -45,6 +45,8 @@ import protobuf_unittest.UnittestMset.TestMessageSet;
 import protobuf_unittest.UnittestMset.RawMessageSet;
 import protobuf_unittest.UnittestMset.RawMessageSet;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
 
 
 /**
 /**
  * Tests related to parsing and serialization.
  * Tests related to parsing and serialization.
@@ -100,6 +102,32 @@ public class WireFormatTest extends TestCase {
     assertEquals(rawBytes, rawBytes2);
     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 {
   public void testParseExtensions() throws Exception {
     // TestAllTypes and TestAllExtensions should have compatible wire formats,
     // TestAllTypes and TestAllExtensions should have compatible wire formats,
     // so if we serialize a TestAllTypes then parse it as TestAllExtensions
     // so if we serialize a TestAllTypes then parse it as TestAllExtensions
@@ -129,6 +157,43 @@ public class WireFormatTest extends TestCase {
     TestUtil.assertPackedExtensionsSet(message2);
     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 {
   public void testExtensionsSerializedSize() throws Exception {
     assertEquals(TestUtil.getAllSet().getSerializedSize(),
     assertEquals(TestUtil.getAllSet().getSerializedSize(),
                  TestUtil.getAllExtensionsSet().getSerializedSize());
                  TestUtil.getAllExtensionsSet().getSerializedSize());

+ 6 - 2
python/google/protobuf/internal/containers.py

@@ -112,9 +112,11 @@ class RepeatedScalarFieldContainer(BaseContainer):
       return
       return
 
 
     orig_empty = len(self._values) == 0
     orig_empty = len(self._values) == 0
+    new_values = []
     for elem in elem_seq:
     for elem in elem_seq:
       self._type_checker.CheckValue(elem)
       self._type_checker.CheckValue(elem)
-    self._values.extend(elem_seq)
+      new_values.append(elem)
+    self._values.extend(new_values)
     self._message_listener.ByteSizeDirty()
     self._message_listener.ByteSizeDirty()
     if orig_empty:
     if orig_empty:
       self._message_listener.TransitionToNonempty()
       self._message_listener.TransitionToNonempty()
@@ -139,9 +141,11 @@ class RepeatedScalarFieldContainer(BaseContainer):
 
 
   def __setslice__(self, start, stop, values):
   def __setslice__(self, start, stop, values):
     """Sets the subset of items from between the specified indices."""
     """Sets the subset of items from between the specified indices."""
+    new_values = []
     for value in values:
     for value in values:
       self._type_checker.CheckValue(value)
       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()
     self._message_listener.ByteSizeDirty()
 
 
   def __delitem__(self, key):
   def __delitem__(self, key):

+ 2 - 2
python/google/protobuf/internal/decoder.py

@@ -135,12 +135,12 @@ class Decoder(object):
   def ReadFloat(self):
   def ReadFloat(self):
     """Reads and returns a 4-byte floating-point number."""
     """Reads and returns a 4-byte floating-point number."""
     serialized = self._stream.ReadBytes(4)
     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):
   def ReadDouble(self):
     """Reads and returns an 8-byte floating-point number."""
     """Reads and returns an 8-byte floating-point number."""
     serialized = self._stream.ReadBytes(8)
     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):
   def ReadBool(self):
     """Reads and returns a bool."""
     """Reads and returns a bool."""

+ 11 - 7
python/google/protobuf/internal/decoder_test.py

@@ -36,12 +36,12 @@ __author__ = 'robinson@google.com (Will Robinson)'
 
 
 import struct
 import struct
 import unittest
 import unittest
-from google.protobuf.internal import wire_format
-from google.protobuf.internal import encoder
 from google.protobuf.internal import decoder
 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 input_stream
+from google.protobuf.internal import wire_format
 from google.protobuf import message
 from google.protobuf import message
+import logging
 import mox
 import mox
 
 
 
 
@@ -110,6 +110,10 @@ class DecoderTest(unittest.TestCase):
     self.mox.VerifyAll()
     self.mox.VerifyAll()
     self.mox.ResetAll()
     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):
   def testReadScalars(self):
     test_string = 'I can feel myself getting sutpider.'
     test_string = 'I can feel myself getting sutpider.'
     scalar_tests = [
     scalar_tests = [
@@ -125,10 +129,10 @@ class DecoderTest(unittest.TestCase):
          'ReadLittleEndian32', long(0xffffffff)],
          'ReadLittleEndian32', long(0xffffffff)],
         ['sfixed64', decoder.Decoder.ReadSFixed64, long(-1),
         ['sfixed64', decoder.Decoder.ReadSFixed64, long(-1),
          'ReadLittleEndian64', 0xffffffffffffffff],
          '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],
         ['bool', decoder.Decoder.ReadBool, True, 'ReadVarUInt32', 1],
         ['enum', decoder.Decoder.ReadEnum, 23, 'ReadVarUInt32', 23],
         ['enum', decoder.Decoder.ReadEnum, 23, 'ReadVarUInt32', 23],
         ['string', decoder.Decoder.ReadString,
         ['string', decoder.Decoder.ReadString,

+ 4 - 2
python/google/protobuf/internal/encoder.py

@@ -123,11 +123,13 @@ class Encoder(object):
 
 
   def AppendFloatNoTag(self, value):
   def AppendFloatNoTag(self, value):
     """Appends a floating-point number to our buffer."""
     """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):
   def AppendDoubleNoTag(self, value):
     """Appends a double-precision floating-point number to our buffer."""
     """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):
   def AppendBoolNoTag(self, value):
     """Appends a boolean to our buffer."""
     """Appends a boolean to our buffer."""

+ 8 - 4
python/google/protobuf/internal/encoder_test.py

@@ -123,6 +123,10 @@ class EncoderTest(unittest.TestCase):
     self.mox.VerifyAll()
     self.mox.VerifyAll()
     self.mox.ResetAll()
     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):
   def testAppendScalars(self):
     utf8_bytes = '\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'
     utf8_bytes = '\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'
     utf8_string = unicode(utf8_bytes, 'utf-8')
     utf8_string = unicode(utf8_bytes, 'utf-8')
@@ -144,9 +148,9 @@ class EncoderTest(unittest.TestCase):
         ['sfixed64', self.encoder.AppendSFixed64, 'AppendLittleEndian64',
         ['sfixed64', self.encoder.AppendSFixed64, 'AppendLittleEndian64',
          wire_format.WIRETYPE_FIXED64, -1, 0xffffffffffffffff],
          wire_format.WIRETYPE_FIXED64, -1, 0xffffffffffffffff],
         ['float', self.encoder.AppendFloat, 'AppendRawBytes',
         ['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',
         ['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',
         ['bool', self.encoder.AppendBool, 'AppendVarint32',
          wire_format.WIRETYPE_VARINT, False],
          wire_format.WIRETYPE_VARINT, False],
         ['enum', self.encoder.AppendEnum, 'AppendVarint32',
         ['enum', self.encoder.AppendEnum, 'AppendVarint32',
@@ -185,9 +189,9 @@ class EncoderTest(unittest.TestCase):
         ['sfixed64', self.encoder.AppendSFixed64NoTag,
         ['sfixed64', self.encoder.AppendSFixed64NoTag,
          'AppendLittleEndian64', None, 0],
          'AppendLittleEndian64', None, 0],
         ['float', self.encoder.AppendFloatNoTag,
         ['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,
         ['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],
         ['bool', self.encoder.AppendBoolNoTag, 'AppendVarint32', None, 0],
         ['enum', self.encoder.AppendEnumNoTag, 'AppendVarint32', None, 0],
         ['enum', self.encoder.AppendEnumNoTag, 'AppendVarint32', None, 0],
         ['sint32', self.encoder.AppendSInt32NoTag,
         ['sint32', self.encoder.AppendSInt32NoTag,

+ 53 - 0
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()

+ 84 - 4
python/google/protobuf/internal/reflection_test.py

@@ -232,13 +232,14 @@ class ReflectionTest(unittest.TestCase):
     proto.repeated_string.extend(['foo', 'bar'])
     proto.repeated_string.extend(['foo', 'bar'])
     proto.repeated_string.extend([])
     proto.repeated_string.extend([])
     proto.repeated_string.append('baz')
     proto.repeated_string.append('baz')
+    proto.repeated_string.extend(str(x) for x in xrange(2))
     proto.optional_int32 = 21
     proto.optional_int32 = 21
     self.assertEqual(
     self.assertEqual(
       [ (proto.DESCRIPTOR.fields_by_name['optional_int32'  ], 21),
       [ (proto.DESCRIPTOR.fields_by_name['optional_int32'  ], 21),
         (proto.DESCRIPTOR.fields_by_name['repeated_int32'  ], [5, 11]),
         (proto.DESCRIPTOR.fields_by_name['repeated_int32'  ], [5, 11]),
         (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]),
         (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]),
         (proto.DESCRIPTOR.fields_by_name['repeated_string' ],
         (proto.DESCRIPTOR.fields_by_name['repeated_string' ],
-          ['foo', 'bar', 'baz']) ],
+          ['foo', 'bar', 'baz', '0', '1']) ],
       proto.ListFields())
       proto.ListFields())
 
 
   def testSingularListExtensions(self):
   def testSingularListExtensions(self):
@@ -447,6 +448,10 @@ class ReflectionTest(unittest.TestCase):
     self.assertEqual([25, 20, 15], proto.repeated_int32[1:4])
     self.assertEqual([25, 20, 15], proto.repeated_int32[1:4])
     self.assertEqual([5, 25, 20, 15, 30], proto.repeated_int32[:])
     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.
     # Test slice assignment.
     proto.repeated_int32[1:4] = [35, 40, 45]
     proto.repeated_int32[1:4] = [35, 40, 45]
     self.assertEqual([5, 35, 40, 45, 30], proto.repeated_int32)
     self.assertEqual([5, 35, 40, 45, 30], proto.repeated_int32)
@@ -1739,13 +1744,14 @@ class SerializationTest(unittest.TestCase):
     self.assertEqual(2, proto2.b)
     self.assertEqual(2, proto2.b)
     self.assertEqual(3, proto2.c)
     self.assertEqual(3, proto2.c)
 
 
-  def testSerializedAllPackedFields(self):
+  def testSerializeAllPackedFields(self):
     first_proto = unittest_pb2.TestPackedTypes()
     first_proto = unittest_pb2.TestPackedTypes()
     second_proto = unittest_pb2.TestPackedTypes()
     second_proto = unittest_pb2.TestPackedTypes()
     test_util.SetAllPackedFields(first_proto)
     test_util.SetAllPackedFields(first_proto)
     serialized = first_proto.SerializeToString()
     serialized = first_proto.SerializeToString()
     self.assertEqual(first_proto.ByteSize(), len(serialized))
     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)
     self.assertEqual(first_proto, second_proto)
 
 
   def testSerializeAllPackedExtensions(self):
   def testSerializeAllPackedExtensions(self):
@@ -1753,7 +1759,8 @@ class SerializationTest(unittest.TestCase):
     second_proto = unittest_pb2.TestPackedExtensions()
     second_proto = unittest_pb2.TestPackedExtensions()
     test_util.SetAllPackedExtensions(first_proto)
     test_util.SetAllPackedExtensions(first_proto)
     serialized = first_proto.SerializeToString()
     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)
     self.assertEqual(first_proto, second_proto)
 
 
   def testMergePackedFromStringWhenSomeFieldsAlreadySet(self):
   def testMergePackedFromStringWhenSomeFieldsAlreadySet(self):
@@ -1838,6 +1845,79 @@ class SerializationTest(unittest.TestCase):
     self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER,
     self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER,
       51)
       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):
 class OptionsTest(unittest.TestCase):
 
 
   def testMessageOptions(self):
   def testMessageOptions(self):

+ 197 - 1
python/google/protobuf/internal/test_util.py

@@ -38,6 +38,7 @@ __author__ = 'robinson@google.com (Will Robinson)'
 
 
 import os.path
 import os.path
 
 
+import unittest
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_pb2
 
 
@@ -351,6 +352,200 @@ def ExpectAllFieldsAndExtensionsInOrder(serialized):
   if expected != serialized:
   if expected != serialized:
     raise ValueError('Expected %r, found %r' % (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):
 def GoldenFile(filename):
   """Finds the given golden file and returns a file object representing it."""
   """Finds the given golden file and returns a file object representing it."""
 
 
@@ -359,7 +554,8 @@ def GoldenFile(filename):
   while os.path.exists(path):
   while os.path.exists(path):
     if os.path.exists(os.path.join(path, 'src/google/protobuf')):
     if os.path.exists(os.path.join(path, 'src/google/protobuf')):
       # Found it.  Load the golden file from the testdata directory.
       # 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, '..')
     path = os.path.join(path, '..')
 
 
   raise RuntimeError(
   raise RuntimeError(

+ 278 - 3
python/google/protobuf/internal/text_format_test.py

@@ -42,11 +42,16 @@ from google.protobuf.internal import test_util
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_mset_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)
     f = test_util.GoldenFile(golden_filename)
     golden_lines = f.readlines()
     golden_lines = f.readlines()
     f.close()
     f.close()
+    return golden_lines
+
+  def CompareToGoldenFile(self, text, golden_filename):
+    golden_lines = self.ReadGolden(golden_filename)
     self.CompareToGoldenLines(text, golden_lines)
     self.CompareToGoldenLines(text, golden_lines)
 
 
   def CompareToGoldenText(self, text, golden_text):
   def CompareToGoldenText(self, text, golden_text):
@@ -117,6 +122,276 @@ class TextFormatTest(unittest.TestCase):
     return text.replace('e+0','e+').replace('e+0','e+') \
     return text.replace('e+0','e+').replace('e+0','e+') \
                .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__':
 if __name__ == '__main__':
   unittest.main()
   unittest.main()
-

+ 4 - 2
python/google/protobuf/internal/type_checkers.py

@@ -122,8 +122,10 @@ class UnicodeValueChecker(object):
       try:
       try:
         unicode(proposed_value, 'ascii')
         unicode(proposed_value, 'ascii')
       except UnicodeDecodeError:
       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):
 class Int32ValueChecker(IntValueChecker):

+ 2 - 0
python/google/protobuf/internal/wire_format.py

@@ -64,6 +64,8 @@ UINT64_MAX = (1 << 64) - 1
 # "struct" format strings that will encode/decode the specified formats.
 # "struct" format strings that will encode/decode the specified formats.
 FORMAT_UINT32_LITTLE_ENDIAN = '<I'
 FORMAT_UINT32_LITTLE_ENDIAN = '<I'
 FORMAT_UINT64_LITTLE_ENDIAN = '<Q'
 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
 # We'll have to provide alternate implementations of AppendLittleEndian*() on

+ 1 - 2
python/google/protobuf/message.py

@@ -36,7 +36,6 @@
 
 
 __author__ = 'robinson@google.com (Will Robinson)'
 __author__ = 'robinson@google.com (Will Robinson)'
 
 
-from google.protobuf import text_format
 
 
 class Error(Exception): pass
 class Error(Exception): pass
 class DecodeError(Error): pass
 class DecodeError(Error): pass
@@ -76,7 +75,7 @@ class Message(object):
     return not self == other_msg
     return not self == other_msg
 
 
   def __str__(self):
   def __str__(self):
-    return text_format.MessageToString(self)
+    raise NotImplementedError
 
 
   def MergeFrom(self, other_msg):
   def MergeFrom(self, other_msg):
     """Merges the contents of the specified message into current message.
     """Merges the contents of the specified message into current message.

+ 56 - 10
python/google/protobuf/reflection.py

@@ -62,6 +62,7 @@ from google.protobuf.internal import type_checkers
 from google.protobuf.internal import wire_format
 from google.protobuf.internal import wire_format
 from google.protobuf import descriptor as descriptor_mod
 from google.protobuf import descriptor as descriptor_mod
 from google.protobuf import message as message_mod
 from google.protobuf import message as message_mod
+from google.protobuf import text_format
 
 
 _FieldDescriptor = descriptor_mod.FieldDescriptor
 _FieldDescriptor = descriptor_mod.FieldDescriptor
 
 
@@ -291,7 +292,7 @@ def _DefaultValueForField(message, field):
 def _AddInitMethod(message_descriptor, cls):
 def _AddInitMethod(message_descriptor, cls):
   """Adds an __init__ method to cls."""
   """Adds an __init__ method to cls."""
   fields = message_descriptor.fields
   fields = message_descriptor.fields
-  def init(self):
+  def init(self, **kwargs):
     self._cached_byte_size = 0
     self._cached_byte_size = 0
     self._cached_byte_size_dirty = False
     self._cached_byte_size_dirty = False
     self._listener = message_listener_mod.NullMessageListener()
     self._listener = message_listener_mod.NullMessageListener()
@@ -306,12 +307,30 @@ def _AddInitMethod(message_descriptor, cls):
       if field.label != _FieldDescriptor.LABEL_REPEATED:
       if field.label != _FieldDescriptor.LABEL_REPEATED:
         setattr(self, _HasFieldName(field.name), False)
         setattr(self, _HasFieldName(field.name), False)
     self.Extensions = _ExtensionDict(self, cls._known_extensions)
     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.__module__ = None
   init.__doc__ = None
   init.__doc__ = None
   cls.__init__ = init
   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):
 def _AddPropertiesForFields(descriptor, cls):
   """Adds properties for all fields in this protocol message type."""
   """Adds properties for all fields in this protocol message type."""
   for field in descriptor.fields:
   for field in descriptor.fields:
@@ -543,10 +562,7 @@ def _AddHasFieldMethod(cls):
 def _AddClearFieldMethod(cls):
 def _AddClearFieldMethod(cls):
   """Helper for _AddMessageMethods()."""
   """Helper for _AddMessageMethods()."""
   def ClearField(self, field_name):
   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
     proto_field_name = field.name
     python_field_name = _ValueFieldName(proto_field_name)
     python_field_name = _ValueFieldName(proto_field_name)
     has_field_name = _HasFieldName(proto_field_name)
     has_field_name = _HasFieldName(proto_field_name)
@@ -629,6 +645,13 @@ def _AddEqualsMethod(message_descriptor, cls):
   cls.__eq__ = __eq__
   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):
 def _AddSetListenerMethod(cls):
   """Helper for _AddMessageMethods()."""
   """Helper for _AddMessageMethods()."""
   def SetListener(self, listener):
   def SetListener(self, listener):
@@ -1090,7 +1113,7 @@ def _DeserializeOneEntity(message_descriptor, message, decoder):
       content_start = decoder.Position()
       content_start = decoder.Position()
       while decoder.Position() - content_start < length:
       while decoder.Position() - content_start < length:
         element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
         element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
-      return decoder.Position() - content_start
+      return decoder.Position() - initial_position
   else:
   else:
     # Repeated composite.
     # Repeated composite.
     composite = element_list.add()
     composite = element_list.add()
@@ -1275,6 +1298,7 @@ def _AddMessageMethods(message_descriptor, cls):
   _AddClearMethod(cls)
   _AddClearMethod(cls)
   _AddHasExtensionMethod(cls)
   _AddHasExtensionMethod(cls)
   _AddEqualsMethod(message_descriptor, cls)
   _AddEqualsMethod(message_descriptor, cls)
+  _AddStrMethod(message_descriptor, cls)
   _AddSetListenerMethod(cls)
   _AddSetListenerMethod(cls)
   _AddByteSizeMethod(message_descriptor, cls)
   _AddByteSizeMethod(message_descriptor, cls)
   _AddSerializeToStringMethod(message_descriptor, cls)
   _AddSerializeToStringMethod(message_descriptor, cls)
@@ -1436,6 +1460,20 @@ class _ExtensionDict(object):
             if extension.label != _FieldDescriptor.LABEL_REPEATED)
             if extension.label != _FieldDescriptor.LABEL_REPEATED)
     self._has_bits = dict.fromkeys(keys, False)
     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):
   def __getitem__(self, extension_handle):
     """Returns the current value of the given extension handle."""
     """Returns the current value of the given extension handle."""
     # We don't care as much about keeping critical sections short in the
     # We don't care as much about keeping critical sections short in the
@@ -1609,7 +1647,15 @@ class _ExtensionDict(object):
     Returns: A dict mapping field_number to (handle, field_descriptor),
     Returns: A dict mapping field_number to (handle, field_descriptor),
       for *all* registered extensions for this dict.
       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)

+ 3 - 2
python/google/protobuf/service.py

@@ -67,8 +67,6 @@ class Service(object):
     and "done" will later be called with the response value.
     and "done" will later be called with the response value.
 
 
     In the blocking case, RpcException will be raised on error.
     In the blocking case, RpcException will be raised on error.
-    Asynchronous calls must check status via the Failed method of the
-    RpcController.
 
 
     Preconditions:
     Preconditions:
     * method_descriptor.service == GetDescriptor
     * method_descriptor.service == GetDescriptor
@@ -82,6 +80,9 @@ class Service(object):
     Postconditions:
     Postconditions:
     * "done" will be called when the method is complete.  This may be
     * "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.
       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
     raise NotImplementedError
 
 

+ 526 - 1
python/google/protobuf/text_format.py

@@ -33,10 +33,19 @@
 __author__ = 'kenton@google.com (Kenton Varda)'
 __author__ = 'kenton@google.com (Kenton Varda)'
 
 
 import cStringIO
 import cStringIO
+import re
 
 
+from collections import deque
+from google.protobuf.internal import type_checkers
 from google.protobuf import descriptor
 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):
 def MessageToString(message):
   out = cStringIO.StringIO()
   out = cStringIO.StringIO()
@@ -45,6 +54,7 @@ def MessageToString(message):
   out.close()
   out.close()
   return result
   return result
 
 
+
 def PrintMessage(message, out, indent = 0):
 def PrintMessage(message, out, indent = 0):
   for field, value in message.ListFields():
   for field, value in message.ListFields():
     if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
     if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
@@ -53,6 +63,7 @@ def PrintMessage(message, out, indent = 0):
     else:
     else:
       PrintField(field, value, out, indent)
       PrintField(field, value, out, indent)
 
 
+
 def PrintField(field, value, out, indent = 0):
 def PrintField(field, value, out, indent = 0):
   """Print a single field name/value pair.  For repeated fields, the value
   """Print a single field name/value pair.  For repeated fields, the value
   should be a single element."""
   should be a single element."""
@@ -82,6 +93,7 @@ def PrintField(field, value, out, indent = 0):
   PrintFieldValue(field, value, out, indent)
   PrintFieldValue(field, value, out, indent)
   out.write('\n')
   out.write('\n')
 
 
+
 def PrintFieldValue(field, value, out, indent = 0):
 def PrintFieldValue(field, value, out, indent = 0):
   """Print a single field value (not including name).  For repeated fields,
   """Print a single field value (not including name).  For repeated fields,
   the value should be a single element."""
   the value should be a single element."""
@@ -104,6 +116,507 @@ def PrintFieldValue(field, value, out, indent = 0):
   else:
   else:
     out.write(str(value))
     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
 # text.encode('string_escape') does not seem to satisfy our needs as it
 # encodes unprintable characters using two-digit hex escapes whereas our
 # encodes unprintable characters using two-digit hex escapes whereas our
 # C++ unescaping function allows hex escapes to be any length.  So,
 # C++ unescaping function allows hex escapes to be any length.  So,
@@ -123,3 +636,15 @@ def _CEscape(text):
     if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes
     if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes
     return c
     return c
   return "".join([escape(c) for c in text])
   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')

+ 34 - 3
src/Makefile.am

@@ -43,21 +43,25 @@ nobase_include_HEADERS =                                       \
   google/protobuf/descriptor_database.h                        \
   google/protobuf/descriptor_database.h                        \
   google/protobuf/dynamic_message.h                            \
   google/protobuf/dynamic_message.h                            \
   google/protobuf/extension_set.h                              \
   google/protobuf/extension_set.h                              \
+  google/protobuf/generated_message_util.h                     \
   google/protobuf/generated_message_reflection.h               \
   google/protobuf/generated_message_reflection.h               \
   google/protobuf/message.h                                    \
   google/protobuf/message.h                                    \
+  google/protobuf/message_lite.h                               \
   google/protobuf/reflection_ops.h                             \
   google/protobuf/reflection_ops.h                             \
   google/protobuf/repeated_field.h                             \
   google/protobuf/repeated_field.h                             \
   google/protobuf/service.h                                    \
   google/protobuf/service.h                                    \
   google/protobuf/text_format.h                                \
   google/protobuf/text_format.h                                \
   google/protobuf/unknown_field_set.h                          \
   google/protobuf/unknown_field_set.h                          \
   google/protobuf/wire_format.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                            \
   google/protobuf/io/coded_stream.h                            \
   $(GZHEADERS)                                                 \
   $(GZHEADERS)                                                 \
   google/protobuf/io/printer.h                                 \
   google/protobuf/io/printer.h                                 \
   google/protobuf/io/tokenizer.h                               \
   google/protobuf/io/tokenizer.h                               \
   google/protobuf/io/zero_copy_stream.h                        \
   google/protobuf/io/zero_copy_stream.h                        \
   google/protobuf/io/zero_copy_stream_impl.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/code_generator.h                    \
   google/protobuf/compiler/command_line_interface.h            \
   google/protobuf/compiler/command_line_interface.h            \
   google/protobuf/compiler/importer.h                          \
   google/protobuf/compiler/importer.h                          \
@@ -68,6 +72,8 @@ nobase_include_HEADERS =                                       \
 
 
 lib_LTLIBRARIES = libprotobuf.la libprotoc.la
 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_LIBADD = $(PTHREAD_LIBS)
 libprotobuf_la_LDFLAGS = -version-info 3:0:0
 libprotobuf_la_LDFLAGS = -version-info 3:0:0
 libprotobuf_la_SOURCES =                                       \
 libprotobuf_la_SOURCES =                                       \
@@ -89,20 +95,25 @@ libprotobuf_la_SOURCES =                                       \
   google/protobuf/descriptor_database.cc                       \
   google/protobuf/descriptor_database.cc                       \
   google/protobuf/dynamic_message.cc                           \
   google/protobuf/dynamic_message.cc                           \
   google/protobuf/extension_set.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/generated_message_reflection.cc              \
   google/protobuf/message.cc                                   \
   google/protobuf/message.cc                                   \
+  google/protobuf/message_lite.cc                              \
   google/protobuf/reflection_ops.cc                            \
   google/protobuf/reflection_ops.cc                            \
   google/protobuf/repeated_field.cc                            \
   google/protobuf/repeated_field.cc                            \
   google/protobuf/service.cc                                   \
   google/protobuf/service.cc                                   \
   google/protobuf/text_format.cc                               \
   google/protobuf/text_format.cc                               \
   google/protobuf/unknown_field_set.cc                         \
   google/protobuf/unknown_field_set.cc                         \
   google/protobuf/wire_format.cc                               \
   google/protobuf/wire_format.cc                               \
+  google/protobuf/wire_format_lite.cc                          \
   google/protobuf/io/coded_stream.cc                           \
   google/protobuf/io/coded_stream.cc                           \
   google/protobuf/io/gzip_stream.cc                            \
   google/protobuf/io/gzip_stream.cc                            \
   google/protobuf/io/printer.cc                                \
   google/protobuf/io/printer.cc                                \
   google/protobuf/io/tokenizer.cc                              \
   google/protobuf/io/tokenizer.cc                              \
   google/protobuf/io/zero_copy_stream.cc                       \
   google/protobuf/io/zero_copy_stream.cc                       \
   google/protobuf/io/zero_copy_stream_impl.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/importer.cc                         \
   google/protobuf/compiler/parser.cc
   google/protobuf/compiler/parser.cc
 
 
@@ -171,6 +182,9 @@ protoc_inputs =                                                \
   google/protobuf/unittest_optimize_for.proto                  \
   google/protobuf/unittest_optimize_for.proto                  \
   google/protobuf/unittest_embed_optimize_for.proto            \
   google/protobuf/unittest_embed_optimize_for.proto            \
   google/protobuf/unittest_custom_options.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
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
 
 
 EXTRA_DIST =                                                   \
 EXTRA_DIST =                                                   \
@@ -186,7 +200,14 @@ EXTRA_DIST =                                                   \
   google/protobuf/io/package_info.h                            \
   google/protobuf/io/package_info.h                            \
   google/protobuf/compiler/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_outputs =                                               \
+  $(protoc_lite_outputs)                                       \
   google/protobuf/unittest.pb.cc                               \
   google/protobuf/unittest.pb.cc                               \
   google/protobuf/unittest.pb.h                                \
   google/protobuf/unittest.pb.h                                \
   google/protobuf/unittest_empty.pb.cc                         \
   google/protobuf/unittest_empty.pb.cc                         \
@@ -201,6 +222,8 @@ protoc_outputs =                                               \
   google/protobuf/unittest_embed_optimize_for.pb.h             \
   google/protobuf/unittest_embed_optimize_for.pb.h             \
   google/protobuf/unittest_custom_options.pb.cc                \
   google/protobuf/unittest_custom_options.pb.cc                \
   google/protobuf/unittest_custom_options.pb.h                 \
   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.cc  \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
 
 
@@ -240,7 +263,7 @@ COMMON_TEST_SOURCES =                                          \
   google/protobuf/testing/file.cc                              \
   google/protobuf/testing/file.cc                              \
   google/protobuf/testing/file.h
   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 \
 protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
                       $(top_builddir)/gtest/lib/libgtest.la       \
                       $(top_builddir)/gtest/lib/libgtest.la       \
                       $(top_builddir)/gtest/lib/libgtest_main.la
                       $(top_builddir)/gtest/lib/libgtest_main.la
@@ -290,6 +313,14 @@ protobuf_lazy_descriptor_test_SOURCES =                        \
   $(COMMON_TEST_SOURCES)
   $(COMMON_TEST_SOURCES)
 nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
 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
 if HAVE_ZLIB
 zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
 zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
 zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
 zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
@@ -298,4 +329,4 @@ zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
 zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
 zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
 endif
 endif
 
 
-TESTS = protobuf-test protobuf-lazy-descriptor-test $(GZTESTS)
+TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZTESTS)

+ 22 - 0
src/google/protobuf/compiler/code_generator.cc

@@ -34,6 +34,8 @@
 
 
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/code_generator.h>
 
 
+#include <google/protobuf/stubs/strutil.h>
+
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
 namespace compiler {
 namespace compiler {
@@ -41,6 +43,26 @@ namespace compiler {
 CodeGenerator::~CodeGenerator() {}
 CodeGenerator::~CodeGenerator() {}
 OutputDirectory::~OutputDirectory() {}
 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 compiler
 }  // namespace protobuf
 }  // namespace protobuf
 }  // namespace google
 }  // namespace google

+ 11 - 0
src/google/protobuf/compiler/code_generator.h

@@ -40,6 +40,8 @@
 
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 #include <string>
 #include <string>
+#include <vector>
+#include <utility>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
@@ -105,6 +107,15 @@ class LIBPROTOC_EXPORT OutputDirectory {
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
   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 compiler
 }  // namespace protobuf
 }  // namespace protobuf
 
 

+ 51 - 28
src/google/protobuf/compiler/cpp/cpp_enum.cc

@@ -95,24 +95,39 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
   }
   }
 
 
   printer->Print(vars,
   printer->Print(vars,
-    "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"
     "$dllexport$bool $classname$_IsValid(int value);\n"
     "$dllexport$bool $classname$_IsValid(int value);\n"
     "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
     "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
     "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
     "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
     "\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) {
 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
@@ -128,24 +143,28 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
   }
   }
 
 
   printer->Print(vars,
   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"
     "static inline bool $nested_name$_IsValid(int value) {\n"
     "  return $classname$_IsValid(value);\n"
     "  return $classname$_IsValid(value);\n"
     "}\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"
     "static const $nested_name$ $nested_name$_MIN =\n"
     "  $classname$_$nested_name$_MIN;\n"
     "  $classname$_$nested_name$_MIN;\n"
     "static const $nested_name$ $nested_name$_MAX =\n"
     "static const $nested_name$ $nested_name$_MAX =\n"
     "  $classname$_$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(
 void EnumGenerator::GenerateDescriptorInitializer(
@@ -168,11 +187,15 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
   map<string, string> vars;
   map<string, string> vars;
   vars["classname"] = classname_;
   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,
   printer->Print(vars,
-    "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_descriptor_;\n"
-    "}\n"
     "bool $classname$_IsValid(int value) {\n"
     "bool $classname$_IsValid(int value) {\n"
     "  switch(value) {\n");
     "  switch(value) {\n");
 
 

+ 4 - 0
src/google/protobuf/compiler/cpp/cpp_enum.h

@@ -63,6 +63,10 @@ class EnumGenerator {
   // nested enums.
   // nested enums.
   void GenerateDefinition(io::Printer* printer);
   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
   // 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
   // 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
   // namespace.  This should be placed inside the class definition in the

+ 52 - 55
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_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.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>
 #include <google/protobuf/stubs/strutil.h>
 
 
 namespace google {
 namespace google {
@@ -43,24 +43,14 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 namespace cpp {
 
 
-using internal::WireFormat;
-
 namespace {
 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,
 void SetEnumVariables(const FieldDescriptor* descriptor,
                       map<string, string>* variables) {
                       map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, variables);
   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
-
-  (*variables)["name"] = FieldName(descriptor);
   (*variables)["type"] = ClassName(descriptor->enum_type(), true);
   (*variables)["type"] = ClassName(descriptor->enum_type(), true);
   (*variables)["default"] = SimpleItoa(default_value->number());
   (*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
 }  // namespace
@@ -83,8 +73,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
 void EnumFieldGenerator::
 void EnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void EnumFieldGenerator::
@@ -124,33 +114,37 @@ void EnumFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "int value;\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"
     "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");
     "}\n");
 }
 }
 
 
 void EnumFieldGenerator::
 void EnumFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void EnumFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void EnumFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
     "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 @@ void RepeatedEnumFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "::google::protobuf::RepeatedField<int> $name$_;\n");
     "::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_,
     printer->Print(variables_,
       "mutable int _$name$_cached_byte_size_;\n");
       "mutable int _$name$_cached_byte_size_;\n");
   }
   }
@@ -177,11 +170,11 @@ GeneratePrivateMembers(io::Printer* printer) const {
 void RepeatedEnumFieldGenerator::
 void RepeatedEnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void RepeatedEnumFieldGenerator::
@@ -238,7 +231,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
           "input->PushLimit(length);\n"
           "input->PushLimit(length);\n"
       "while (input->BytesUntilLimit() > 0) {\n"
       "while (input->BytesUntilLimit() > 0) {\n"
       "  int value;\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"
       "  if ($type$_IsValid(value)) {\n"
       "    add_$name$(static_cast< $type$ >(value));\n"
       "    add_$name$(static_cast< $type$ >(value));\n"
       "  }\n"
       "  }\n"
@@ -247,11 +240,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
   } else {
   } else {
     printer->Print(variables_,
     printer->Print(variables_,
       "int value;\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"
       "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");
       "}\n");
   }
   }
 }
 }
@@ -262,10 +259,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
     // Write the tag and the size.
     // Write the tag and the size.
     printer->Print(variables_,
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
       "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"
       "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
       "}\n");
       "}\n");
   }
   }
@@ -273,12 +270,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
     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 {
   } else {
     printer->Print(variables_,
     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");
   printer->Print("}\n");
 }
 }
@@ -289,24 +286,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
     // Write the tag and the size.
     // Write the tag and the size.
     printer->Print(variables_,
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
       "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("
       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
-          "_$name$_cached_byte_size_, target);\n"
+      "    _$name$_cached_byte_size_, target);\n"
       "}\n");
       "}\n");
   }
   }
   printer->Print(variables_,
   printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
     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 {
   } else {
     printer->Print(variables_,
     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");
   printer->Print("}\n");
 }
 }
@@ -319,15 +316,15 @@ GenerateByteSize(io::Printer* printer) const {
   printer->Indent();
   printer->Indent();
   printer->Print(variables_,
   printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n"
       "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"
       "    this->$name$(i));\n"
       "}\n");
       "}\n");
 
 
   if (descriptor_->options().packed()) {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
     printer->Print(variables_,
       "if (data_size > 0) {\n"
       "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"
       "}\n"
       "_$name$_cached_byte_size_ = data_size;\n"
       "_$name$_cached_byte_size_ = data_size;\n"
       "total_size += data_size;\n");
       "total_size += data_size;\n");

+ 1 - 0
src/google/protobuf/compiler/cpp/cpp_extension.cc

@@ -133,6 +133,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
     vars["global_name"] = global_name;
     vars["global_name"] = global_name;
     printer->Print(vars,
     printer->Print(vars,
       "const ::std::string $global_name$_default($default$);\n");
       "const ::std::string $global_name$_default($default$);\n");
+
     // Update the default to refer to the string global.
     // Update the default to refer to the string global.
     vars["default"] = global_name + "_default";
     vars["default"] = global_name + "_default";
   }
   }

+ 19 - 0
src/google/protobuf/compiler/cpp/cpp_field.cc

@@ -33,18 +33,37 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 
 #include <google/protobuf/compiler/cpp/cpp_field.h>
 #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_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_string_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_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 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() {}
 FieldGenerator::~FieldGenerator() {}
 
 
 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)

+ 10 - 0
src/google/protobuf/compiler/cpp/cpp_field.h

@@ -35,6 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 #define 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/stubs/common.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.h>
 
 
@@ -49,6 +52,13 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 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 {
 class FieldGenerator {
  public:
  public:
   FieldGenerator() {}
   FieldGenerator() {}

+ 183 - 132
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -125,13 +125,18 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
 
 
   // OK, it's now safe to #include other files.
   // OK, it's now safe to #include other files.
   printer->Print(
   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/repeated_field.h>\n"
     "#include <google/protobuf/extension_set.h>\n");
     "#include <google/protobuf/extension_set.h>\n");
 
 
-  if (file_->service_count() > 0) {
+  if (HasDescriptorMethods(file_)) {
     printer->Print(
     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++) {
   for (int i = 0; i < file_->dependency_count(); i++) {
@@ -193,19 +198,21 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
   printer->Print(kThickSeparator);
   printer->Print(kThickSeparator);
   printer->Print("\n");
   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.
   // Declare extension identifiers.
   for (int i = 0; i < file_->extension_count(); i++) {
   for (int i = 0; i < file_->extension_count(); i++) {
@@ -228,6 +235,30 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
   // Close up namespace.
   // Close up namespace.
   GenerateNamespaceClosers(printer);
   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(
   printer->Print(
     "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
     "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
     "filename_identifier", filename_identifier);
     "filename_identifier", filename_identifier);
@@ -237,40 +268,52 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
   printer->Print(
   printer->Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "\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 \"$basename$.pb.h\"\n"
+
     "#include <google/protobuf/stubs/once.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/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()));
     "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);
   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(
     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(
     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);
   GenerateBuildDescriptors(printer);
 
 
   // Generate enums.
   // Generate enums.
@@ -286,12 +329,14 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
     message_generators_[i]->GenerateClassMethods(printer);
     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.
   // Define extensions.
@@ -317,80 +362,84 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
   // anyone calls descriptor() or GetReflection() on one of the types defined
   // anyone calls descriptor() or GetReflection() on one of the types defined
   // in the file.
   // in the 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()));
+  // 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()));
 
 
-  // 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);
-  }
-  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);
-  }
+    // 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);
+    }
+    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");
+    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_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();
 
 
-  // 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);
+    }
 
 
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateTypeRegistrations(printer);
+    printer->Outdent();
+    printer->Print(
+      "}\n"
+      "\n"
+      "}  // namespace\n");
   }
   }
 
 
-  printer->Outdent();
-  printer->Print(
-    "}\n"
-    "\n"
-    "}  // namespace\n");
-
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
 
 
   // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
   // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
@@ -442,32 +491,34 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
       "name", GlobalAddDescriptorsName(dependency->name()));
       "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)));
-  }
-  printer->Print(
-    ", $size$);\n",
-    "size", SimpleItoa(file_data.size()));
+    // 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());
+    // 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
   // Allocate and initialize default instances.  This can't be done lazily
   // since default instances are returned by simple accessors and are used with
   // since default instances are returned by simple accessors and are used with

+ 1 - 28
src/google/protobuf/compiler/cpp/cpp_generator.cc

@@ -42,39 +42,12 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 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() {}
 CppGenerator::~CppGenerator() {}
 CppGenerator::~CppGenerator() {}
 
 
@@ -83,7 +56,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
                             OutputDirectory* output_directory,
                             OutputDirectory* output_directory,
                             string* error) const {
                             string* error) const {
   vector<pair<string, string> > options;
   vector<pair<string, string> > options;
-  ParseOptions(parameter, &options);
+  ParseGeneratorParameter(parameter, &options);
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
   // parse generator options
   // parse generator options

+ 12 - 1
src/google/protobuf/compiler/cpp/cpp_helpers.cc

@@ -152,7 +152,18 @@ string FieldName(const FieldDescriptor* field) {
 
 
 string FieldConstantName(const FieldDescriptor *field) {
 string FieldConstantName(const FieldDescriptor *field) {
   string field_name = UnderscoresToCamelCase(field->name(), true);
   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) {
 string StripProto(const string& filename) {

+ 29 - 0
src/google/protobuf/compiler/cpp/cpp_helpers.h

@@ -37,6 +37,7 @@
 
 
 #include <string>
 #include <string>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
@@ -105,6 +106,34 @@ string GlobalAssignDescriptorsName(const string& filename);
 // Return the name of the ShutdownFile() function for a given file.
 // Return the name of the ShutdownFile() function for a given file.
 string GlobalShutdownFileName(const string& filename);
 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 cpp
 }  // namespace compiler
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace protobuf

+ 335 - 188
src/google/protobuf/compiler/cpp/cpp_message.cc

@@ -34,14 +34,17 @@
 
 
 #include <algorithm>
 #include <algorithm>
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <vector>
 #include <google/protobuf/compiler/cpp/cpp_message.h>
 #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_enum.h>
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/coded_stream.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>
 #include <google/protobuf/descriptor.pb.h>
 
 
 namespace google {
 namespace google {
@@ -50,6 +53,7 @@ namespace compiler {
 namespace cpp {
 namespace cpp {
 
 
 using internal::WireFormat;
 using internal::WireFormat;
+using internal::WireFormatLite;
 
 
 namespace {
 namespace {
 
 
@@ -195,6 +199,16 @@ GenerateEnumDefinitions(io::Printer* printer) {
   }
   }
 }
 }
 
 
+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::
 void MessageGenerator::
 GenerateFieldAccessorDeclarations(io::Printer* printer) {
 GenerateFieldAccessorDeclarations(io::Printer* printer) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -203,17 +217,16 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
     PrintFieldComment(printer, field);
     PrintFieldComment(printer, field);
 
 
     map<string, string> vars;
     map<string, string> vars;
-    vars["name"] = FieldName(field);
+    SetCommonFieldVariables(field, &vars);
     vars["constant_name"] = FieldConstantName(field);
     vars["constant_name"] = FieldConstantName(field);
-    vars["number"] = SimpleItoa(field->number());
 
 
     if (field->is_repeated()) {
     if (field->is_repeated()) {
-      printer->Print(vars, "inline int $name$_size() const;\n");
+      printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
     } else {
     } 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");
     printer->Print(vars, "static const int $constant_name$ = $number$;\n");
 
 
     // Generate type-specific accessor declarations.
     // Generate type-specific accessor declarations.
@@ -241,9 +254,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
     PrintFieldComment(printer, field);
     PrintFieldComment(printer, field);
 
 
     map<string, string> vars;
     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().
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
     if (field->is_repeated()) {
@@ -297,9 +308,11 @@ GenerateClassDefinition(io::Printer* printer) {
   } else {
   } else {
     vars["dllexport"] = dllexport_decl_ + " ";
     vars["dllexport"] = dllexport_decl_ + " ";
   }
   }
+  vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ?
+                       "Message" : "MessageLite";
 
 
   printer->Print(vars,
   printer->Print(vars,
-    "class $dllexport$$classname$ : public ::google::protobuf::Message {\n"
+    "class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n"
     " public:\n");
     " public:\n");
   printer->Indent();
   printer->Indent();
 
 
@@ -313,16 +326,28 @@ GenerateClassDefinition(io::Printer* printer) {
     "  CopyFrom(from);\n"
     "  CopyFrom(from);\n"
     "  return *this;\n"
     "  return *this;\n"
     "}\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"
     "static const $classname$& default_instance();\n"
     "void Swap($classname$* other);\n"
     "void Swap($classname$* other);\n"
     "\n"
     "\n"
@@ -330,28 +355,29 @@ GenerateClassDefinition(io::Printer* printer) {
     "\n"
     "\n"
     "$classname$* New() const;\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,
     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 CopyFrom(const $classname$& from);\n"
       "void MergeFrom(const $classname$& from);\n"
       "void MergeFrom(const $classname$& from);\n"
       "void Clear();\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");
         "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
     }
     }
   }
   }
@@ -363,10 +389,19 @@ GenerateClassDefinition(io::Printer* printer) {
     "void SharedDtor();\n"
     "void SharedDtor();\n"
     "void SetCachedSize(int size) const { _cached_size_ = size; }\n"
     "void SetCachedSize(int size) const { _cached_size_ = size; }\n"
     "public:\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"
     "// nested types ----------------------------------------------------\n"
     "\n");
     "\n");
 
 
@@ -411,9 +446,13 @@ GenerateClassDefinition(io::Printer* printer) {
       "::google::protobuf::internal::ExtensionSet _extensions_;\n");
       "::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.
   // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
   printer->Print(
   printer->Print(
-    "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
     "mutable int _cached_size_;\n"
     "mutable int _cached_size_;\n"
     "\n");
     "\n");
   for (int i = 0; i < descriptor_->field_count(); i++) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -431,7 +470,8 @@ GenerateClassDefinition(io::Printer* printer) {
       GlobalAddDescriptorsName(descriptor_->file()->name()));
       GlobalAddDescriptorsName(descriptor_->file()->name()));
   printer->Print(
   printer->Print(
     "friend void $assigndescriptorsname$();\n"
     "friend void $assigndescriptorsname$();\n"
-    "friend void $shutdownfilename$();\n",
+    "friend void $shutdownfilename$();\n"
+    "\n",
     "assigndescriptorsname",
     "assigndescriptorsname",
       GlobalAssignDescriptorsName(descriptor_->file()->name()),
       GlobalAssignDescriptorsName(descriptor_->file()->name()),
     "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
     "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
@@ -605,10 +645,15 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
 void MessageGenerator::
 void MessageGenerator::
 GenerateShutdownCode(io::Printer* printer) {
 GenerateShutdownCode(io::Printer* printer) {
   printer->Print(
   printer->Print(
-    "delete $classname$::default_instance_;\n"
-    "delete $classname$_reflection_;\n",
+    "delete $classname$::default_instance_;\n",
     "classname", classname_);
     "classname", classname_);
 
 
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(
+      "delete $classname$_reflection_;\n",
+      "classname", classname_);
+  }
+
   // Handle nested types.
   // Handle nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     nested_generators_[i]->GenerateShutdownCode(printer);
     nested_generators_[i]->GenerateShutdownCode(printer);
@@ -655,29 +700,24 @@ GenerateClassMethods(io::Printer* printer) {
   GenerateStructors(printer);
   GenerateStructors(printer);
   printer->Print("\n");
   printer->Print("\n");
 
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_->file())) {
     GenerateClear(printer);
     GenerateClear(printer);
     printer->Print("\n");
     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);
       GenerateSerializeWithCachedSizesToArray(printer);
       printer->Print("\n");
       printer->Print("\n");
-
-      GenerateByteSize(printer);
-      printer->Print("\n");
     }
     }
 
 
+    GenerateByteSize(printer);
+    printer->Print("\n");
+
     GenerateMergeFrom(printer);
     GenerateMergeFrom(printer);
     printer->Print("\n");
     printer->Print("\n");
 
 
@@ -691,16 +731,26 @@ GenerateClassMethods(io::Printer* printer) {
   GenerateSwap(printer);
   GenerateSwap(printer);
   printer->Print("\n");
   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::
 void MessageGenerator::
@@ -723,18 +773,6 @@ GenerateOffsets(io::Printer* printer) {
   printer->Print("};\n");
   printer->Print("};\n");
 }
 }
 
 
-void MessageGenerator::
-GenerateInitializerList(io::Printer* printer) {
-  printer->Indent();
-  printer->Indent();
-
-  printer->Print(
-    "::google::protobuf::Message()");
-
-  printer->Outdent();
-  printer->Outdent();
-}
-
 void MessageGenerator::
 void MessageGenerator::
 GenerateSharedConstructorCode(io::Printer* printer) {
 GenerateSharedConstructorCode(io::Printer* printer) {
   printer->Print(
   printer->Print(
@@ -797,17 +835,14 @@ void MessageGenerator::
 GenerateStructors(io::Printer* printer) {
 GenerateStructors(io::Printer* printer) {
   // Generate the default constructor.
   // Generate the default constructor.
   printer->Print(
   printer->Print(
-      "$classname$::$classname$()\n"
-      "  : ",
-      "classname", classname_);
-  GenerateInitializerList(printer);
-  printer->Print(" {\n"
+    "$classname$::$classname$() {\n"
     "  SharedCtor();\n"
     "  SharedCtor();\n"
-    "}\n");
+    "}\n",
+    "classname", classname_);
 
 
   printer->Print(
   printer->Print(
     "\n"
     "\n"
-    "void $classname$::InitAsDefaultInstance() {",
+    "void $classname$::InitAsDefaultInstance() {\n",
     "classname", classname_);
     "classname", classname_);
 
 
   // The default instance needs all of its embedded message pointers
   // The default instance needs all of its embedded message pointers
@@ -833,15 +868,12 @@ GenerateStructors(io::Printer* printer) {
 
 
   // Generate the copy constructor.
   // Generate the copy constructor.
   printer->Print(
   printer->Print(
-      "$classname$::$classname$(const $classname$& from)\n"
-      "  : ",
-      "classname", classname_);
-  GenerateInitializerList(printer);
-  printer->Print(" {\n"
+    "$classname$::$classname$(const $classname$& from) {\n"
     "  SharedCtor();\n"
     "  SharedCtor();\n"
     "  MergeFrom(from);\n"
     "  MergeFrom(from);\n"
     "}\n"
     "}\n"
-    "\n");
+    "\n",
+    "classname", classname_);
 
 
   // Generate the shared constructor code.
   // Generate the shared constructor code.
   GenerateSharedConstructorCode(printer);
   GenerateSharedConstructorCode(printer);
@@ -857,12 +889,21 @@ GenerateStructors(io::Printer* printer) {
   // Generate the shared destructor code.
   // Generate the shared destructor code.
   GenerateSharedDestructorCode(printer);
   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(
   printer->Print(
-    "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_descriptor_;\n"
-    "}\n"
-    "\n"
     "const $classname$& $classname$::default_instance() {\n"
     "const $classname$& $classname$::default_instance() {\n"
     "  if (default_instance_ == NULL) $adddescriptorsname$();"
     "  if (default_instance_ == NULL) $adddescriptorsname$();"
     "  return *default_instance_;\n"
     "  return *default_instance_;\n"
@@ -951,8 +992,12 @@ GenerateClear(io::Printer* printer) {
   }
   }
 
 
   printer->Print(
   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->Outdent();
   printer->Print("}\n");
   printer->Print("}\n");
@@ -967,7 +1012,7 @@ GenerateSwap(io::Printer* printer) {
   printer->Print("if (other != this) {\n");
   printer->Print("if (other != this) {\n");
   printer->Indent();
   printer->Indent();
 
 
-  if ( descriptor_->file()->options().optimize_for() == FileOptions::SPEED ) {
+  if (HasGeneratedMethods(descriptor_->file())) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* field = descriptor_->field(i);
       const FieldDescriptor* field = descriptor_->field(i);
       field_generators_.get(field).GenerateSwappingCode(printer);
       field_generators_.get(field).GenerateSwappingCode(printer);
@@ -978,7 +1023,9 @@ GenerateSwap(io::Printer* printer) {
                      "i", SimpleItoa(i));
                      "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");
     printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
     if (descriptor_->extension_range_count() > 0) {
     if (descriptor_->extension_range_count() > 0) {
       printer->Print("_extensions_.Swap(&other->_extensions_);\n");
       printer->Print("_extensions_.Swap(&other->_extensions_);\n");
@@ -987,7 +1034,6 @@ GenerateSwap(io::Printer* printer) {
     printer->Print("GetReflection()->Swap(this, other);");
     printer->Print("GetReflection()->Swap(this, other);");
   }
   }
 
 
-
   printer->Outdent();
   printer->Outdent();
   printer->Print("}\n");
   printer->Print("}\n");
   printer->Outdent();
   printer->Outdent();
@@ -996,31 +1042,42 @@ GenerateSwap(io::Printer* printer) {
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateMergeFrom(io::Printer* printer) {
 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.
   // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
   printer->Print(
   printer->Print(
@@ -1082,8 +1139,10 @@ GenerateMergeFrom(io::Printer* printer) {
     printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
     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->Outdent();
   printer->Print("}\n");
   printer->Print("}\n");
@@ -1091,20 +1150,22 @@ GenerateMergeFrom(io::Printer* printer) {
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateCopyFrom(io::Printer* printer) {
 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.
   // Generate the class-specific CopyFrom.
   printer->Print(
   printer->Print(
@@ -1123,6 +1184,18 @@ GenerateCopyFrom(io::Printer* printer) {
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) {
 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(
   printer->Print(
     "bool $classname$::MergePartialFromCodedStream(\n"
     "bool $classname$::MergePartialFromCodedStream(\n"
     "    ::google::protobuf::io::CodedInputStream* input) {\n"
     "    ::google::protobuf::io::CodedInputStream* input) {\n"
@@ -1144,7 +1217,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
     // creates a jump table that is 8x larger and sparser, and meanwhile the
     // creates a jump table that is 8x larger and sparser, and meanwhile the
     // if()s are highly predictable.
     // if()s are highly predictable.
     printer->Print(
     printer->Print(
-      "switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {\n");
+      "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n");
 
 
     printer->Indent();
     printer->Indent();
 
 
@@ -1158,8 +1231,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
 
 
       printer->Print(
       printer->Print(
         "case $number$: {\n"
         "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"
         "    goto handle_uninterpreted;\n"
         "  }\n",
         "  }\n",
         "number", SimpleItoa(field->number()),
         "number", SimpleItoa(field->number()),
@@ -1214,8 +1287,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
 
 
   // Is this an end-group tag?  If so, this must be the end of the message.
   // Is this an end-group tag?  If so, this must be the end of the message.
   printer->Print(
   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"
     "  return true;\n"
     "}\n");
     "}\n");
 
 
@@ -1228,10 +1301,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
         descriptor_->extension_range(i);
         descriptor_->extension_range(i);
       if (i > 0) printer->Print(" ||\n    ");
       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) {
       if (range->end > FieldDescriptor::kMaxNumber) {
         printer->Print(
         printer->Print(
@@ -1244,17 +1317,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
           "end", SimpleItoa(end_tag));
           "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"
       "  continue;\n"
       "}\n");
       "}\n");
   }
   }
 
 
   // We really don't recognize this tag.  Skip it.
   // 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) {
   if (descriptor_->field_count() > 0) {
     printer->Print("break;\n");
     printer->Print("break;\n");
@@ -1319,21 +1404,41 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) {
 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(
   printer->Print(
     "void $classname$::SerializeWithCachedSizes(\n"
     "void $classname$::SerializeWithCachedSizes(\n"
     "    ::google::protobuf::io::CodedOutputStream* output) const {\n",
     "    ::google::protobuf::io::CodedOutputStream* output) const {\n",
     "classname", classname_);
     "classname", classname_);
   printer->Indent();
   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);
   GenerateSerializeWithCachedSizesBody(printer, false);
 
 
   printer->Outdent();
   printer->Outdent();
@@ -1343,6 +1448,26 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) {
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
 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(
   printer->Print(
     "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
     "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
     "    ::google::protobuf::uint8* target) const {\n",
     "    ::google::protobuf::uint8* target) const {\n",
@@ -1389,26 +1514,46 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
     }
     }
   }
   }
 
 
-  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 {
+  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(
     printer->Print(
-      "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
-      "    unknown_fields(), output);\n");
+      "}\n");
   }
   }
-  printer->Outdent();
-
-  printer->Print(
-    "}\n");
 }
 }
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateByteSize(io::Printer* printer) {
 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(
   printer->Print(
     "int $classname$::ByteSize() const {\n",
     "int $classname$::ByteSize() const {\n",
     "classname", classname_);
     "classname", classname_);
@@ -1478,14 +1623,16 @@ GenerateByteSize(io::Printer* printer) {
       "\n");
       "\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,
   // We update _cached_size_ even though this is a const method.  In theory,
   // this is not thread-compatible, because concurrent writes have undefined
   // this is not thread-compatible, because concurrent writes have undefined

+ 4 - 5
src/google/protobuf/compiler/cpp/cpp_message.h

@@ -69,6 +69,10 @@ class MessageGenerator {
   // definitions because those classes use the enums definitions).
   // definitions because those classes use the enums definitions).
   void GenerateEnumDefinitions(io::Printer* printer);
   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.
   // Generate definitions for this class and all its nested types.
   void GenerateClassDefinition(io::Printer* printer);
   void GenerateClassDefinition(io::Printer* printer);
 
 
@@ -125,11 +129,6 @@ class MessageGenerator {
   // Generate the shared destructor code.
   // Generate the shared destructor code.
   void GenerateSharedDestructorCode(io::Printer* printer);
   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.
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateClear(io::Printer* printer);
   void GenerateMergeFromCodedStream(io::Printer* printer);
   void GenerateMergeFromCodedStream(io::Printer* printer);

+ 29 - 38
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_message_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/strutil.h>
 
 
 namespace google {
 namespace google {
@@ -43,22 +42,12 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 namespace cpp {
 
 
-using internal::WireFormat;
-
 namespace {
 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,
 void SetMessageVariables(const FieldDescriptor* descriptor,
                          map<string, string>* variables) {
                          map<string, string>* variables) {
-  (*variables)["name"] = FieldName(descriptor);
+  SetCommonFieldVariables(descriptor, variables);
   (*variables)["type"] = ClassName(descriptor->message_type(), true);
   (*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
 }  // namespace
@@ -81,8 +70,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
 void MessageFieldGenerator::
 void MessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void MessageFieldGenerator::
@@ -124,35 +113,35 @@ void MessageFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
     printer->Print(variables_,
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
       "     input, mutable_$name$()));\n");
       "     input, mutable_$name$()));\n");
   } else {
   } else {
     printer->Print(variables_,
     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::
 void MessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void MessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void MessageFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
     "total_size += $tag_size$ +\n"
-    "  ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
+    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
     "    this->$name$());\n");
     "    this->$name$());\n");
 }
 }
 
 
@@ -175,11 +164,13 @@ GeneratePrivateMembers(io::Printer* printer) const {
 void RepeatedMessageFieldGenerator::
 void RepeatedMessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void RepeatedMessageFieldGenerator::
@@ -228,12 +219,12 @@ void RepeatedMessageFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
     printer->Print(variables_,
     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 {
   } else {
     printer->Print(variables_,
     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 @@ void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
     "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");
     "}\n");
 }
 }
 
 
@@ -250,9 +241,9 @@ void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
     "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");
     "}\n");
 }
 }
 
 
@@ -262,7 +253,7 @@ GenerateByteSize(io::Printer* printer) const {
     "total_size += $tag_size$ * this->$name$_size();\n"
     "total_size += $tag_size$ * this->$name$_size();\n"
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
     "for (int i = 0; i < this->$name$_size(); i++) {\n"
     "  total_size +=\n"
     "  total_size +=\n"
-    "    ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
+    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
     "      this->$name$(i));\n"
     "      this->$name$(i));\n"
     "}\n");
     "}\n");
 }
 }

+ 50 - 61
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_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.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/strutil.h>
 
 
 namespace google {
 namespace google {
@@ -43,7 +43,7 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 namespace cpp {
 
 
-using internal::WireFormat;
+using internal::WireFormatLite;
 
 
 namespace {
 namespace {
 
 
@@ -57,14 +57,14 @@ int FixedSize(FieldDescriptor::Type type) {
     case FieldDescriptor::TYPE_UINT64  : return -1;
     case FieldDescriptor::TYPE_UINT64  : return -1;
     case FieldDescriptor::TYPE_SINT32  : return -1;
     case FieldDescriptor::TYPE_SINT32  : return -1;
     case FieldDescriptor::TYPE_SINT64  : 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_BOOL    : return WireFormat::kBoolSize;
+    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 WireFormatLite::kBoolSize;
     case FieldDescriptor::TYPE_ENUM    : return -1;
     case FieldDescriptor::TYPE_ENUM    : return -1;
 
 
     case FieldDescriptor::TYPE_STRING  : return -1;
     case FieldDescriptor::TYPE_STRING  : return -1;
@@ -79,20 +79,11 @@ int FixedSize(FieldDescriptor::Type type) {
   return -1;
   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,
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
                            map<string, string>* variables) {
                            map<string, string>* variables) {
-  (*variables)["name"] = FieldName(descriptor);
+  SetCommonFieldVariables(descriptor, variables);
   (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
   (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
   (*variables)["default"] = DefaultValue(descriptor);
   (*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());
   int fixed_size = FixedSize(descriptor->type());
   if (fixed_size != -1) {
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
@@ -119,8 +110,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
 void PrimitiveFieldGenerator::
 void PrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void PrimitiveFieldGenerator::
@@ -158,7 +149,7 @@ GenerateConstructorCode(io::Printer* printer) const {
 void PrimitiveFieldGenerator::
 void PrimitiveFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
-    "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
+    "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
     "      input, &$name$_));\n"
     "      input, &$name$_));\n"
     "_set_bit($index$);\n");
     "_set_bit($index$);\n");
 }
 }
@@ -166,14 +157,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
 void PrimitiveFieldGenerator::
 void PrimitiveFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
-    "::google::protobuf::internal::WireFormat::Write$declared_type$("
+    "::google::protobuf::internal::WireFormatLite::Write$declared_type$("
       "$number$, this->$name$(), output);\n");
       "$number$, this->$name$(), output);\n");
 }
 }
 
 
 void PrimitiveFieldGenerator::
 void PrimitiveFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   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");
       "$number$, this->$name$(), target);\n");
 }
 }
 
 
@@ -183,7 +174,7 @@ GenerateByteSize(io::Printer* printer) const {
   if (fixed_size == -1) {
   if (fixed_size == -1) {
     printer->Print(variables_,
     printer->Print(variables_,
       "total_size += $tag_size$ +\n"
       "total_size += $tag_size$ +\n"
-      "  ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
+      "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
       "    this->$name$());\n");
       "    this->$name$());\n");
   } else {
   } else {
     printer->Print(variables_,
     printer->Print(variables_,
@@ -205,8 +196,7 @@ void RepeatedPrimitiveFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
     "::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_,
     printer->Print(variables_,
       "mutable int _$name$_cached_byte_size_;\n");
       "mutable int _$name$_cached_byte_size_;\n");
   }
   }
@@ -215,11 +205,12 @@ GeneratePrivateMembers(io::Printer* printer) const {
 void RepeatedPrimitiveFieldGenerator::
 void RepeatedPrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void RepeatedPrimitiveFieldGenerator::
@@ -272,12 +263,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
     printer->Print(variables_,
     printer->Print(variables_,
       "::google::protobuf::uint32 length;\n"
       "::google::protobuf::uint32 length;\n"
       "DO_(input->ReadVarint32(&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"
       "while (input->BytesUntilLimit() > 0) {\n"
       "  $type$ value;\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"
       "  add_$name$(value);\n"
       "}\n"
       "}\n"
       "input->PopLimit(limit);\n");
       "input->PopLimit(limit);\n");
@@ -286,8 +277,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
   } else {
   } else {
     printer->Print(variables_,
     printer->Print(variables_,
       "$type$ value;\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");
       "add_$name$(value);\n");
   }
   }
 }
 }
@@ -298,9 +289,9 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
     // Write the tag and the size.
     // Write the tag and the size.
     printer->Print(variables_,
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
       "if (this->$name$_size() > 0) {\n"
-      "  ::google::protobuf::internal::WireFormat::WriteTag("
+      "  ::google::protobuf::internal::WireFormatLite::WriteTag("
           "$number$, "
           "$number$, "
-          "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
+          "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
           "output);\n"
           "output);\n"
       "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
       "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
       "}\n");
       "}\n");
@@ -309,12 +300,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
     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 {
   } else {
     printer->Print(variables_,
     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");
   printer->Print("}\n");
 }
 }
@@ -325,26 +316,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
     // Write the tag and the size.
     // Write the tag and the size.
     printer->Print(variables_,
     printer->Print(variables_,
       "if (this->$name$_size() > 0) {\n"
       "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");
       "}\n");
   }
   }
   printer->Print(variables_,
   printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
       "for (int i = 0; i < this->$name$_size(); i++) {\n");
   if (descriptor_->options().packed()) {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
     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 {
   } else {
     printer->Print(variables_,
     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");
   printer->Print("}\n");
 }
 }
@@ -359,8 +348,8 @@ GenerateByteSize(io::Printer* printer) const {
   if (fixed_size == -1) {
   if (fixed_size == -1) {
     printer->Print(variables_,
     printer->Print(variables_,
       "for (int i = 0; i < this->$name$_size(); i++) {\n"
       "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");
       "}\n");
   } else {
   } else {
     printer->Print(variables_,
     printer->Print(variables_,
@@ -370,8 +359,8 @@ GenerateByteSize(io::Printer* printer) const {
   if (descriptor_->options().packed()) {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
     printer->Print(variables_,
       "if (data_size > 0) {\n"
       "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"
       "}\n"
       "_$name$_cached_byte_size_ = data_size;\n"
       "_$name$_cached_byte_size_ = data_size;\n"
       "total_size += data_size;\n");
       "total_size += data_size;\n");

+ 1 - 1
src/google/protobuf/compiler/cpp/cpp_service.cc

@@ -249,7 +249,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
     sub_vars["input_type"] = ClassName(method->input_type(), true);
     sub_vars["input_type"] = ClassName(method->input_type(), true);
     sub_vars["output_type"] = ClassName(method->output_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.
     //   not references.
     printer->Print(sub_vars,
     printer->Print(sub_vars,
       "    case $index$:\n"
       "    case $index$:\n"

+ 84 - 45
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_string_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format_inl.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/strutil.h>
 
 
@@ -44,23 +43,13 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace cpp {
 namespace cpp {
 
 
-using internal::WireFormat;
-
 namespace {
 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,
 void SetStringVariables(const FieldDescriptor* descriptor,
                         map<string, string>* variables) {
                         map<string, string>* variables) {
-  (*variables)["name"] = FieldName(descriptor);
+  SetCommonFieldVariables(descriptor, variables);
   (*variables)["default"] =
   (*variables)["default"] =
     "\"" + CEscape(descriptor->default_value_string()) + "\"";
     "\"" + 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"] =
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
 }
 }
@@ -111,11 +100,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
   }
   }
 
 
   printer->Print(variables_,
   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()) {
   if (descriptor_->options().has_ctype()) {
     printer->Outdent();
     printer->Outdent();
@@ -221,29 +211,52 @@ GenerateDestructorCode(io::Printer* printer) const {
 void StringFieldGenerator::
 void StringFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void StringFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 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_,
   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::
 void StringFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 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_,
   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::
 void StringFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
     "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 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
   }
   }
 
 
   printer->Print(variables_,
   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 "
     "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()) {
   if (descriptor_->options().has_ctype()) {
     printer->Outdent();
     printer->Outdent();
@@ -361,26 +378,48 @@ GenerateConstructorCode(io::Printer* printer) const {
 void RepeatedStringFieldGenerator::
 void RepeatedStringFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
   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::
 void RepeatedStringFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   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");
     "}\n");
 }
 }
 
 
 void RepeatedStringFieldGenerator::
 void RepeatedStringFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   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");
     "}\n");
 }
 }
 
 
@@ -389,7 +428,7 @@ GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "total_size += $tag_size$ * this->$name$_size();\n"
     "total_size += $tag_size$ * this->$name$_size();\n"
     "for (int i = 0; i < this->$name$_size(); i++) {\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"
     "    this->$name$(i));\n"
     "}\n");
     "}\n");
 }
 }

+ 50 - 14
src/google/protobuf/compiler/cpp/cpp_unittest.cc

@@ -50,11 +50,9 @@
 #include <google/protobuf/unittest_optimize_for.pb.h>
 #include <google/protobuf/unittest_optimize_for.pb.h>
 #include <google/protobuf/unittest_embed_optimize_for.pb.h>
 #include <google/protobuf/unittest_embed_optimize_for.pb.h>
 #include <google/protobuf/test_util.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/cpp/cpp_test_bad_identifiers.pb.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/io/coded_stream.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/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -75,18 +73,6 @@ namespace cpp {
 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
 namespace cpp_unittest {
 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 {
 class MockErrorCollector : public MultiFileErrorCollector {
  public:
  public:
@@ -157,6 +143,19 @@ TEST(GeneratedMessageTest, Defaults) {
             &message.optional_import_message());
             &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) {
 TEST(GeneratedMessageTest, Accessors) {
   // Set every field to a unique value then go back and check all those
   // Set every field to a unique value then go back and check all those
   // values.
   // values.
@@ -710,6 +709,32 @@ TEST(GeneratedMessageTest, TestSpaceUsed) {
 
 
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 #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) {
 TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
@@ -803,6 +828,17 @@ TEST(GeneratedEnumTest, Parse) {
   EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value));
   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
 #endif  // PROTOBUF_TEST_NO_DESCRIPTORS
 
 
 // ===================================================================
 // ===================================================================

+ 84 - 64
src/google/protobuf/compiler/java/java_enum.cc

@@ -67,14 +67,17 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
 EnumGenerator::~EnumGenerator() {}
 EnumGenerator::~EnumGenerator() {}
 
 
 void EnumGenerator::Generate(io::Printer* printer) {
 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();
   printer->Indent();
 
 
   for (int i = 0; i < canonical_values_.size(); i++) {
   for (int i = 0; i < canonical_values_.size(); i++) {
@@ -126,63 +129,78 @@ void EnumGenerator::Generate(io::Printer* printer) {
     "    default: return null;\n"
     "    default: return null;\n"
     "  }\n"
     "  }\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
   // 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(
     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()));
-  }
+      "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(
-    "}\n"
-    "\n"
-    "private static final $classname$[] VALUES = {\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());
+    }
 
 
-  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"
-    "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(
   printer->Print(
@@ -194,14 +212,16 @@ void EnumGenerator::Generate(io::Printer* printer) {
     "}\n",
     "}\n",
     "classname", descriptor_->name());
     "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->Outdent();
   printer->Print("}\n\n");
   printer->Print("}\n\n");

+ 26 - 17
src/google/protobuf/compiler/java/java_enum_field.cc

@@ -39,7 +39,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.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/strutil.h>
 
 
 namespace google {
 namespace google {
@@ -53,18 +53,13 @@ namespace {
 //   repeat code between this and the other field types.
 //   repeat code between this and the other field types.
 void SetEnumVariables(const FieldDescriptor* descriptor,
 void SetEnumVariables(const FieldDescriptor* descriptor,
                       map<string, string>* variables) {
                       map<string, string>* variables) {
-  const EnumValueDescriptor* default_value;
-  default_value = descriptor->default_value_enum();
-
-  string type = ClassName(descriptor->enum_type());
-
   (*variables)["name"] =
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
     UnderscoresToCapitalizedCamelCase(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*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"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
   (*variables)["tag_size"] = SimpleItoa(
       internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
       internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
@@ -132,10 +127,17 @@ void EnumFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "int rawValue = input.readEnum();\n"
     "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"
     "  set$capitalized_name$(value);\n"
     "}\n");
     "}\n");
 }
 }
@@ -185,7 +187,7 @@ GenerateMembers(io::Printer* printer) const {
     "}\n");
     "}\n");
 
 
   if (descriptor_->options().packed() &&
   if (descriptor_->options().packed() &&
-      descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+      HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
       "private int $name$MemoizedSerializedSize;\n");
   }
   }
@@ -272,10 +274,17 @@ GenerateParsingCode(io::Printer* printer) const {
   // Read and store the enum
   // Read and store the enum
   printer->Print(variables_,
   printer->Print(variables_,
     "int rawValue = input.readEnum();\n"
     "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"
     "  add$capitalized_name$(value);\n"
     "}\n");
     "}\n");
 
 

+ 85 - 14
src/google/protobuf/compiler/java/java_extension.cc

@@ -42,6 +42,39 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace java {
 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)
 ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor)
   : descriptor_(descriptor) {
   : descriptor_(descriptor) {
   if (descriptor_->extension_scope() != NULL) {
   if (descriptor_->extension_scope() != NULL) {
@@ -59,6 +92,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
   vars["containing_type"] = ClassName(descriptor_->containing_type());
   vars["containing_type"] = ClassName(descriptor_->containing_type());
   vars["number"] = SimpleItoa(descriptor_->number());
   vars["number"] = SimpleItoa(descriptor_->number());
   vars["constant_name"] = FieldConstantName(descriptor_);
   vars["constant_name"] = FieldConstantName(descriptor_);
+  vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite";
 
 
   JavaType java_type = GetJavaType(descriptor_);
   JavaType java_type = GetJavaType(descriptor_);
   string singular_type;
   string singular_type;
@@ -79,13 +113,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
   if (descriptor_->is_repeated()) {
   if (descriptor_->is_repeated()) {
     printer->Print(vars,
     printer->Print(vars,
       "public static\n"
       "public static\n"
-      "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
       "    $containing_type$,\n"
       "    $containing_type$,\n"
       "    java.util.List<$type$>> $name$;\n");
       "    java.util.List<$type$>> $name$;\n");
   } else {
   } else {
     printer->Print(vars,
     printer->Print(vars,
       "public static\n"
       "public static\n"
-      "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
       "    $containing_type$,\n"
       "    $containing_type$,\n"
       "    $type$> $name$;\n");
       "    $type$> $name$;\n");
   }
   }
@@ -96,34 +130,71 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
   vars["name"] = UnderscoresToCamelCase(descriptor_);
   vars["name"] = UnderscoresToCamelCase(descriptor_);
   vars["scope"] = scope_;
   vars["scope"] = scope_;
   vars["index"] = SimpleItoa(descriptor_->index());
   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_);
   JavaType java_type = GetJavaType(descriptor_);
   string singular_type;
   string singular_type;
   switch (java_type) {
   switch (java_type) {
     case JAVATYPE_MESSAGE:
     case JAVATYPE_MESSAGE:
       vars["type"] = ClassName(descriptor_->message_type());
       vars["type"] = ClassName(descriptor_->message_type());
+      vars["prototype"] = ClassName(descriptor_->message_type()) +
+                          ".getDefaultInstance()";
       break;
       break;
     case JAVATYPE_ENUM:
     case JAVATYPE_ENUM:
       vars["type"] = ClassName(descriptor_->enum_type());
       vars["type"] = ClassName(descriptor_->enum_type());
+      vars["enum_map"] = ClassName(descriptor_->enum_type()) +
+                         ".internalGetValueMap()";
       break;
       break;
     default:
     default:
       vars["type"] = BoxedPrimitiveTypeName(java_type);
       vars["type"] = BoxedPrimitiveTypeName(java_type);
       break;
       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 {
   } 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");
+    }
   }
   }
 }
 }
 
 

+ 38 - 5
src/google/protobuf/compiler/java/java_file.cc

@@ -151,7 +151,9 @@ void FileGenerator::Generate(io::Printer* printer) {
 
 
   printer->Print(
   printer->Print(
     "public static void registerAllExtensions(\n"
     "public static void registerAllExtensions(\n"
-    "    com.google.protobuf.ExtensionRegistry registry) {\n");
+    "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
+    "lite", HasDescriptorMethods(file_) ? "" : "Lite");
+
   printer->Indent();
   printer->Indent();
 
 
   for (int i = 0; i < file_->extension_count(); i++) {
   for (int i = 0; i < file_->extension_count(); i++) {
@@ -195,8 +197,42 @@ void FileGenerator::Generate(io::Printer* printer) {
 
 
   printer->Print("\n");
   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
   // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
   // and embed it as a string literal, which is parsed and built into real
   // 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
   // descriptors at initialization time.  We unfortunately have to put it in
@@ -310,9 +346,6 @@ void FileGenerator::Generate(io::Printer* printer) {
   printer->Outdent();
   printer->Outdent();
   printer->Print(
   printer->Print(
     "}\n");
     "}\n");
-
-  printer->Outdent();
-  printer->Print("}\n");
 }
 }
 
 
 template<typename GeneratorClass, typename DescriptorClass>
 template<typename GeneratorClass, typename DescriptorClass>

+ 2 - 0
src/google/protobuf/compiler/java/java_file.h

@@ -81,6 +81,8 @@ class FileGenerator {
   string java_package_;
   string java_package_;
   string classname_;
   string classname_;
 
 
+  void GenerateEmbeddedDescriptor(io::Printer* printer);
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
 };
 
 

+ 1 - 27
src/google/protobuf/compiler/java/java_generator.cc

@@ -45,32 +45,6 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace java {
 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() {}
 JavaGenerator::~JavaGenerator() {}
 JavaGenerator::~JavaGenerator() {}
 
 
@@ -79,7 +53,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
                              OutputDirectory* output_directory,
                              OutputDirectory* output_directory,
                              string* error) const {
                              string* error) const {
   vector<pair<string, string> > options;
   vector<pair<string, string> > options;
-  ParseOptions(parameter, &options);
+  ParseGeneratorParameter(parameter, &options);
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
   // parse generator options
   // parse generator options

+ 67 - 0
src/google/protobuf/compiler/java/java_helpers.cc

@@ -37,6 +37,7 @@
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
@@ -243,6 +244,72 @@ const char* BoxedPrimitiveTypeName(JavaType type) {
   return NULL;
   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 java
 }  // namespace compiler
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace protobuf

+ 30 - 0
src/google/protobuf/compiler/java/java_helpers.h

@@ -36,6 +36,7 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 
 
 #include <string>
 #include <string>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.h>
 
 
 namespace google {
 namespace google {
@@ -115,6 +116,35 @@ inline JavaType GetJavaType(const FieldDescriptor* field) {
 // types.
 // types.
 const char* BoxedPrimitiveTypeName(JavaType type);
 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 java
 }  // namespace compiler
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace protobuf

+ 300 - 178
src/google/protobuf/compiler/java/java_message.cc

@@ -41,7 +41,7 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/coded_stream.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>
 #include <google/protobuf/descriptor.pb.h>
 
 
 namespace google {
 namespace google {
@@ -50,6 +50,7 @@ namespace compiler {
 namespace java {
 namespace java {
 
 
 using internal::WireFormat;
 using internal::WireFormat;
+using internal::WireFormatLite;
 
 
 namespace {
 namespace {
 
 
@@ -153,38 +154,41 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor)
 MessageGenerator::~MessageGenerator() {}
 MessageGenerator::~MessageGenerator() {}
 
 
 void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
 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.
-
-  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 ";
-  }
+  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());
+    }
+    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");
+    // 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");
+    // 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.
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -196,41 +200,44 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
 
 
 void MessageGenerator::GenerateStaticVariableInitializers(
 void MessageGenerator::GenerateStaticVariableInitializers(
     io::Printer* printer) {
     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.
   // Generate static member initializers for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -252,18 +259,35 @@ void MessageGenerator::Generate(io::Printer* printer) {
     descriptor_->file()->options().java_multiple_files();
     descriptor_->file()->options().java_multiple_files();
 
 
   if (descriptor_->extension_range_count() > 0) {
   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 {
   } 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->Indent();
   printer->Print(
   printer->Print(
@@ -280,20 +304,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
     "}\n"
     "}\n"
     "\n",
     "\n",
     "classname", descriptor_->name());
     "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
   // Nested types and extensions
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -318,7 +345,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
     printer->Print("\n");
     printer->Print("\n");
   }
   }
 
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_)) {
     GenerateIsInitialized(printer);
     GenerateIsInitialized(printer);
     GenerateMessageSerializationMethods(printer);
     GenerateMessageSerializationMethods(printer);
   }
   }
@@ -326,12 +353,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
   GenerateParseFromMethods(printer);
   GenerateParseFromMethods(printer);
   GenerateBuilder(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(
   printer->Print(
     "\n"
     "\n"
     "static {\n"
     "static {\n"
-    "  $file$.getDescriptor();\n"
+    "  $file$.internalForceInit();\n"
     "}\n",
     "}\n",
     "file", ClassName(descriptor_->file()));
     "file", ClassName(descriptor_->file()));
 
 
@@ -360,9 +398,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
   printer->Indent();
   printer->Indent();
 
 
   if (descriptor_->extension_range_count() > 0) {
   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.
   // Merge the fields and the extension ranges, both sorted by field number.
@@ -380,12 +427,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
     }
     }
   }
   }
 
 
-  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();
   printer->Outdent();
@@ -406,16 +455,23 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
   }
   }
 
 
   if (descriptor_->extension_range_count() > 0) {
   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();
   printer->Outdent();
@@ -439,7 +495,7 @@ GenerateParseFromMethods(io::Printer* printer) {
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data,\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"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
     "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
     "           .buildParsed();\n"
     "           .buildParsed();\n"
@@ -450,7 +506,7 @@ GenerateParseFromMethods(io::Printer* printer) {
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    byte[] data,\n"
     "    byte[] data,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
     "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
     "           .buildParsed();\n"
     "           .buildParsed();\n"
@@ -461,7 +517,7 @@ GenerateParseFromMethods(io::Printer* printer) {
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    java.io.InputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
     "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
     "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
     "           .buildParsed();\n"
     "           .buildParsed();\n"
@@ -472,7 +528,7 @@ GenerateParseFromMethods(io::Printer* printer) {
     "}\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    java.io.InputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
     "  return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
     "  return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
     "           .buildParsed();\n"
     "           .buildParsed();\n"
@@ -484,7 +540,7 @@ GenerateParseFromMethods(io::Printer* printer) {
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.CodedInputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
     "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
     "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
     "           .buildParsed();\n"
     "           .buildParsed();\n"
@@ -509,32 +565,57 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
 
 
 void MessageGenerator::GenerateBuilder(io::Printer* printer) {
 void MessageGenerator::GenerateBuilder(io::Printer* printer) {
   printer->Print(
   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"
     "public static Builder newBuilder($classname$ prototype) {\n"
-    "  return new Builder().mergeFrom(prototype);\n"
+    "  return newBuilder().mergeFrom(prototype);\n"
     "}\n"
     "}\n"
     "public Builder toBuilder() { return newBuilder(this); }\n"
     "public Builder toBuilder() { return newBuilder(this); }\n"
     "\n",
     "\n",
     "classname", ClassName(descriptor_));
     "classname", ClassName(descriptor_));
 
 
   if (descriptor_->extension_range_count() > 0) {
   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 {
   } 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();
   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);
   GenerateCommonBuilderMethods(printer);
 
 
-  if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+  if (HasGeneratedMethods(descriptor_)) {
     GenerateBuilderParsingMethods(printer);
     GenerateBuilderParsingMethods(printer);
   }
   }
 
 
@@ -553,10 +634,19 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
 
 
 void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
 void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
   printer->Print(
   printer->Print(
+    "private $classname$ result;\n"
+    "\n"
     "// Construct using $classname$.newBuilder()\n"
     "// Construct using $classname$.newBuilder()\n"
     "private Builder() {}\n"
     "private Builder() {}\n"
     "\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"
     "\n"
     "@Override\n"
     "@Override\n"
     "protected $classname$ internalGetResult() {\n"
     "protected $classname$ internalGetResult() {\n"
@@ -565,25 +655,38 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
     "\n"
     "\n"
     "@Override\n"
     "@Override\n"
     "public Builder clear() {\n"
     "public Builder clear() {\n"
+    "  if (result == null) {\n"
+    "    throw new IllegalStateException(\n"
+    "      \"Cannot call clear() after build().\");\n"
+    "  }\n"
     "  result = new $classname$();\n"
     "  result = new $classname$();\n"
     "  return this;\n"
     "  return this;\n"
     "}\n"
     "}\n"
     "\n"
     "\n"
     "@Override\n"
     "@Override\n"
     "public Builder clone() {\n"
     "public Builder clone() {\n"
-    "  return new Builder().mergeFrom(result);\n"
+    "  return create().mergeFrom(result);\n"
     "}\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"
     "public $classname$ getDefaultInstanceForType() {\n"
     "  return $classname$.getDefaultInstance();\n"
     "  return $classname$.getDefaultInstance();\n"
     "}\n"
     "}\n"
-    "\n",
+    "\n"
+    "public boolean isInitialized() {\n"
+    "  return result.isInitialized();\n"
+    "}\n",
     "classname", ClassName(descriptor_));
     "classname", ClassName(descriptor_));
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
@@ -592,8 +695,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
     "public $classname$ build() {\n"
     "public $classname$ build() {\n"
     // If result == null, we'll throw an appropriate exception later.
     // If result == null, we'll throw an appropriate exception later.
     "  if (result != null && !isInitialized()) {\n"
     "  if (result != null && !isInitialized()) {\n"
-    "    throw new com.google.protobuf.UninitializedMessageException(\n"
-    "      result);\n"
+    "    throw newUninitializedMessageException(result);\n"
     "  }\n"
     "  }\n"
     "  return buildPartial();\n"
     "  return buildPartial();\n"
     "}\n"
     "}\n"
@@ -601,7 +703,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
     "private $classname$ buildParsed()\n"
     "private $classname$ buildParsed()\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  if (!isInitialized()) {\n"
     "  if (!isInitialized()) {\n"
-    "    throw new com.google.protobuf.UninitializedMessageException(\n"
+    "    throw newUninitializedMessageException(\n"
     "      result).asInvalidProtocolBufferException();\n"
     "      result).asInvalidProtocolBufferException();\n"
     "  }\n"
     "  }\n"
     "  return buildPartial();\n"
     "  return buildPartial();\n"
@@ -610,7 +712,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
     "public $classname$ buildPartial() {\n"
     "public $classname$ buildPartial() {\n"
     "  if (result == null) {\n"
     "  if (result == null) {\n"
     "    throw new IllegalStateException(\n"
     "    throw new IllegalStateException(\n"
-    "      \"build() has already been called on this Builder.\");"
+    "      \"build() has already been called on this Builder.\");\n"
     "  }\n",
     "  }\n",
     "classname", ClassName(descriptor_));
     "classname", ClassName(descriptor_));
   printer->Indent();
   printer->Indent();
@@ -623,6 +725,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
   printer->Print(
   printer->Print(
     "  $classname$ returnMe = result;\n"
     "  $classname$ returnMe = result;\n"
     "  result = null;\n"
     "  result = null;\n"
+    "  builders.get().offer(this);\n"
     "  return returnMe;\n"
     "  return returnMe;\n"
     "}\n"
     "}\n"
     "\n",
     "\n",
@@ -630,18 +733,25 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
 
 
-  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(
     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"
       "public Builder mergeFrom($classname$ other) {\n"
       // Optimization:  If other is the default instance, we know none of its
       // Optimization:  If other is the default instance, we know none of its
       //   fields are set so we can skip the merge.
       //   fields are set so we can skip the merge.
@@ -661,8 +771,12 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
         "  this.mergeExtensionFields(other);\n");
         "  this.mergeExtensionFields(other);\n");
     }
     }
 
 
+    if (HasUnknownFields(descriptor_)) {
+      printer->Print(
+        "  this.mergeUnknownFields(other.getUnknownFields());\n");
+    }
+
     printer->Print(
     printer->Print(
-      "  this.mergeUnknownFields(other.getUnknownFields());\n"
       "  return this;\n"
       "  return this;\n"
       "}\n"
       "}\n"
       "\n");
       "\n");
@@ -676,25 +790,21 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
     SortFieldsByNumber(descriptor_));
     SortFieldsByNumber(descriptor_));
 
 
   printer->Print(
   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"
     "@Override\n"
     "public Builder mergeFrom(\n"
     "public Builder mergeFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.CodedInputStream input,\n"
-    "    com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n");
     "    throws java.io.IOException {\n");
   printer->Indent();
   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(
   printer->Print(
-    "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
-    "  com.google.protobuf.UnknownFieldSet.newBuilder(\n"
-    "    this.getUnknownFields());\n"
     "while (true) {\n");
     "while (true) {\n");
   printer->Indent();
   printer->Indent();
 
 
@@ -703,22 +813,34 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
     "switch (tag) {\n");
     "switch (tag) {\n");
   printer->Indent();
   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++) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = sorted_fields[i];
     const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormat::MakeTag(field->number(),
+    uint32 tag = WireFormatLite::MakeTag(field->number(),
       WireFormat::WireTypeForField(field));
       WireFormat::WireTypeForField(field));
 
 
     printer->Print(
     printer->Print(

+ 22 - 81
src/google/protobuf/compiler/java/java_primitive_field.cc

@@ -39,9 +39,8 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.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/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
@@ -49,6 +48,7 @@ namespace compiler {
 namespace java {
 namespace java {
 
 
 using internal::WireFormat;
 using internal::WireFormat;
+using internal::WireFormatLite;
 
 
 namespace {
 namespace {
 
 
@@ -121,16 +121,6 @@ const char* GetCapitalizedType(const FieldDescriptor* field) {
   return NULL;
   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
 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
 // returns -1.
 // returns -1.
 int FixedSize(FieldDescriptor::Type type) {
 int FixedSize(FieldDescriptor::Type type) {
@@ -141,14 +131,14 @@ int FixedSize(FieldDescriptor::Type type) {
     case FieldDescriptor::TYPE_UINT64  : return -1;
     case FieldDescriptor::TYPE_UINT64  : return -1;
     case FieldDescriptor::TYPE_SINT32  : return -1;
     case FieldDescriptor::TYPE_SINT32  : return -1;
     case FieldDescriptor::TYPE_SINT64  : 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_BOOL    : return WireFormat::kBoolSize;
+    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 WireFormatLite::kBoolSize;
     case FieldDescriptor::TYPE_ENUM    : return -1;
     case FieldDescriptor::TYPE_ENUM    : return -1;
 
 
     case FieldDescriptor::TYPE_STRING  : return -1;
     case FieldDescriptor::TYPE_STRING  : return -1;
@@ -163,64 +153,6 @@ int FixedSize(FieldDescriptor::Type type) {
   return -1;
   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,
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
                            map<string, string>* variables) {
                            map<string, string>* variables) {
   (*variables)["name"] =
   (*variables)["name"] =
@@ -285,8 +217,17 @@ GenerateBuilderMembers(io::Printer* printer) const {
     "  return this;\n"
     "  return this;\n"
     "}\n"
     "}\n"
     "public Builder clear$capitalized_name$() {\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"
     "  return this;\n"
     "}\n");
     "}\n");
 }
 }
@@ -355,7 +296,7 @@ GenerateMembers(io::Printer* printer) const {
     "}\n");
     "}\n");
 
 
   if (descriptor_->options().packed() &&
   if (descriptor_->options().packed() &&
-      descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+      HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
       "private int $name$MemoizedSerializedSize;\n");
   }
   }

+ 1 - 1
src/google/protobuf/compiler/parser.cc

@@ -661,7 +661,7 @@ bool Parser::ParseOptionAssignment(Message* options) {
   GOOGLE_CHECK(uninterpreted_option_field != NULL)
   GOOGLE_CHECK(uninterpreted_option_field != NULL)
       << "No field named \"uninterpreted_option\" in the Options proto.";
       << "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,
       options->GetReflection()->AddMessage(options,
                                            uninterpreted_option_field));
                                            uninterpreted_option_field));
 
 

+ 66 - 14
src/google/protobuf/descriptor.cc

@@ -798,7 +798,7 @@ namespace {
 
 
 EncodedDescriptorDatabase* generated_database_ = NULL;
 EncodedDescriptorDatabase* generated_database_ = NULL;
 DescriptorPool* generated_pool_ = NULL;
 DescriptorPool* generated_pool_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
+GoogleOnceType generated_pool_init_;
 
 
 void DeleteGeneratedPool() {
 void DeleteGeneratedPool() {
   delete generated_database_;
   delete generated_database_;
@@ -814,7 +814,7 @@ void InitGeneratedPool() {
 }
 }
 
 
 inline void InitGeneratedPoolOnce() {
 inline void InitGeneratedPoolOnce() {
-  GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
+  ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
 }
 }
 
 
 }  // anonymous namespace
 }  // anonymous namespace
@@ -1859,7 +1859,11 @@ class DescriptorBuilder {
   // dependency of this file, it will fail, but will set
   // dependency of this file, it will fail, but will set
   // possible_undeclared_dependency_ to point at that file.  This is only used
   // possible_undeclared_dependency_ to point at that file.  This is only used
   // by AddNotDefinedError() to report a more useful error message.
   // 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_;
   const FileDescriptor* possible_undeclared_dependency_;
+  string possible_undeclared_dependency_name_;
 
 
   void AddError(const string& element_name,
   void AddError(const string& element_name,
                 const Message& descriptor,
                 const Message& descriptor,
@@ -2062,7 +2066,7 @@ class DescriptorBuilder {
                                 Message* options);
                                 Message* options);
 
 
     // A recursive helper function that drills into the intermediate fields
     // 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.
     // innermost message. Returns false and sets an error if so.
     bool ExamineIfOptionIsSet(
     bool ExamineIfOptionIsSet(
         vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
         vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
@@ -2233,8 +2237,9 @@ void DescriptorBuilder::AddNotDefinedError(
              "\"" + undefined_symbol + "\" is not defined.");
              "\"" + undefined_symbol + "\" is not defined.");
   } else {
   } else {
     AddError(element_name, descriptor, location,
     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 "
              "imported by \"" + filename_ + "\".  To use it here, please "
              "add the necessary import.");
              "add the necessary import.");
   }
   }
@@ -2295,11 +2300,16 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) {
     // symbol unless none of the dependencies define it.
     // symbol unless none of the dependencies define it.
     if (IsInPackage(file_, name)) return result;
     if (IsInPackage(file_, name)) return result;
     for (int i = 0; i < file_->dependency_count(); i++) {
     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_ = file;
+  possible_undeclared_dependency_name_ = name;
   return kNullSymbol;
   return kNullSymbol;
 }
 }
 
 
@@ -3592,12 +3602,38 @@ void DescriptorBuilder::CrossLinkMethod(
                             proto.array_name(i));                  \
                             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,
 void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
                                             const FileDescriptorProto& proto) {
                                             const FileDescriptorProto& proto) {
   VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
   VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
   VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
   VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
   VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
   VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
   VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
   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,
 void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
@@ -3647,6 +3683,17 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
                "MessageSets cannot have fields, only extensions.");
                "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,
 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
@@ -3660,6 +3707,12 @@ void DescriptorBuilder::ValidateEnumValueOptions(
 }
 }
 void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
 void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
     const ServiceDescriptorProto& proto) {
     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);
   VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
 }
 }
 
 
@@ -3761,7 +3814,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
   const int num_uninterpreted_options = original_options->GetReflection()->
   const int num_uninterpreted_options = original_options->GetReflection()->
       FieldSize(*original_options, original_uninterpreted_options_field);
       FieldSize(*original_options, original_uninterpreted_options_field);
   for (int i = 0; i < num_uninterpreted_options; ++i) {
   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->GetReflection()->GetRepeatedMessage(
             *original_options, original_uninterpreted_options_field, i));
             *original_options, original_uninterpreted_options_field, i));
     if (!InterpretSingleOption(options)) {
     if (!InterpretSingleOption(options)) {
@@ -4009,14 +4062,13 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
       const UnknownField* unknown_field = &unknown_fields.field(i);
       const UnknownField* unknown_field = &unknown_fields.field(i);
       FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
       FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
       // Recurse into the next submessage.
       // Recurse into the next submessage.
-      ++intermediate_fields_iter;
       switch (type) {
       switch (type) {
         case FieldDescriptor::TYPE_MESSAGE:
         case FieldDescriptor::TYPE_MESSAGE:
           if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
           if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
             UnknownFieldSet intermediate_unknown_fields;
             UnknownFieldSet intermediate_unknown_fields;
             if (intermediate_unknown_fields.ParseFromString(
             if (intermediate_unknown_fields.ParseFromString(
                     unknown_field->length_delimited()) &&
                     unknown_field->length_delimited()) &&
-                !ExamineIfOptionIsSet(intermediate_fields_iter,
+                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
                                       intermediate_fields_end,
                                       intermediate_fields_end,
                                       innermost_field, debug_msg_name,
                                       innermost_field, debug_msg_name,
                                       intermediate_unknown_fields)) {
                                       intermediate_unknown_fields)) {
@@ -4027,7 +4079,7 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
 
 
         case FieldDescriptor::TYPE_GROUP:
         case FieldDescriptor::TYPE_GROUP:
           if (unknown_field->type() == UnknownField::TYPE_GROUP) {
           if (unknown_field->type() == UnknownField::TYPE_GROUP) {
-            if (!ExamineIfOptionIsSet(intermediate_fields_iter,
+            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
                                       intermediate_fields_end,
                                       intermediate_fields_end,
                                       innermost_field, debug_msg_name,
                                       innermost_field, debug_msg_name,
                                       unknown_field->group())) {
                                       unknown_field->group())) {
@@ -4139,7 +4191,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
                              option_field->full_name() + "\".");
                              option_field->full_name() + "\".");
       }
       }
       unknown_fields->AddFixed32(option_field->number(),
       unknown_fields->AddFixed32(option_field->number(),
-          google::protobuf::internal::WireFormat::EncodeFloat(value));
+          google::protobuf::internal::WireFormatLite::EncodeFloat(value));
       break;
       break;
     }
     }
 
 
@@ -4156,7 +4208,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
                              option_field->full_name() + "\".");
                              option_field->full_name() + "\".");
       }
       }
       unknown_fields->AddFixed64(option_field->number(),
       unknown_fields->AddFixed64(option_field->number(),
-          google::protobuf::internal::WireFormat::EncodeDouble(value));
+          google::protobuf::internal::WireFormatLite::EncodeDouble(value));
       break;
       break;
     }
     }
 
 
@@ -4267,7 +4319,7 @@ void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
 
 
     case FieldDescriptor::TYPE_SINT32:
     case FieldDescriptor::TYPE_SINT32:
       unknown_fields->AddVarint(number,
       unknown_fields->AddVarint(number,
-          google::protobuf::internal::WireFormat::ZigZagEncode32(value));
+          google::protobuf::internal::WireFormatLite::ZigZagEncode32(value));
       break;
       break;
 
 
     default:
     default:
@@ -4289,7 +4341,7 @@ void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value,
 
 
     case FieldDescriptor::TYPE_SINT64:
     case FieldDescriptor::TYPE_SINT64:
       unknown_fields->AddVarint(number,
       unknown_fields->AddVarint(number,
-          google::protobuf::internal::WireFormat::ZigZagEncode64(value));
+          google::protobuf::internal::WireFormatLite::ZigZagEncode64(value));
       break;
       break;
 
 
     default:
     default:

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 284 - 196
src/google/protobuf/descriptor.pb.cc


+ 125 - 72
src/google/protobuf/descriptor.pb.h

@@ -18,9 +18,10 @@
 #error regenerate this file with a newer version of protoc.
 #error regenerate this file with a newer version of protoc.
 #endif
 #endif
 
 
-#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
 
 
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
@@ -69,11 +70,11 @@ enum FieldDescriptorProto_Type {
   FieldDescriptorProto_Type_TYPE_SINT32 = 17,
   FieldDescriptorProto_Type_TYPE_SINT32 = 17,
   FieldDescriptorProto_Type_TYPE_SINT64 = 18
   FieldDescriptorProto_Type_TYPE_SINT64 = 18
 };
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
 LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
 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_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
 const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
 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) {
 inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
   return ::google::protobuf::internal::NameOfEnum(
   return ::google::protobuf::internal::NameOfEnum(
     FieldDescriptorProto_Type_descriptor(), value);
     FieldDescriptorProto_Type_descriptor(), value);
@@ -88,11 +89,11 @@ enum FieldDescriptorProto_Label {
   FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
   FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
   FieldDescriptorProto_Label_LABEL_REPEATED = 3
   FieldDescriptorProto_Label_LABEL_REPEATED = 3
 };
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
 LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
 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_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
 const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
 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) {
 inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
   return ::google::protobuf::internal::NameOfEnum(
   return ::google::protobuf::internal::NameOfEnum(
     FieldDescriptorProto_Label_descriptor(), value);
     FieldDescriptorProto_Label_descriptor(), value);
@@ -104,13 +105,14 @@ inline bool FieldDescriptorProto_Label_Parse(
 }
 }
 enum FileOptions_OptimizeMode {
 enum FileOptions_OptimizeMode {
   FileOptions_OptimizeMode_SPEED = 1,
   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);
 LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
 const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
 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) {
 inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
   return ::google::protobuf::internal::NameOfEnum(
   return ::google::protobuf::internal::NameOfEnum(
     FileOptions_OptimizeMode_descriptor(), value);
     FileOptions_OptimizeMode_descriptor(), value);
@@ -124,11 +126,11 @@ enum FieldOptions_CType {
   FieldOptions_CType_CORD = 1,
   FieldOptions_CType_CORD = 1,
   FieldOptions_CType_STRING_PIECE = 2
   FieldOptions_CType_STRING_PIECE = 2
 };
 };
-LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
 LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
 LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
 const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
 const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
 const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
 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) {
 inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
   return ::google::protobuf::internal::NameOfEnum(
   return ::google::protobuf::internal::NameOfEnum(
     FieldOptions_CType_descriptor(), value);
     FieldOptions_CType_descriptor(), value);
@@ -187,8 +189,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -212,6 +213,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -277,8 +279,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -384,6 +385,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -449,8 +451,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -479,6 +480,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_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_[(2 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -544,8 +546,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -635,6 +636,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -700,8 +702,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -724,13 +725,17 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
   static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
   static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
   static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
   static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
   static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64;
   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*
   static inline const ::google::protobuf::EnumDescriptor*
   Type_descriptor() {
   Type_descriptor() {
     return FieldDescriptorProto_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) {
   static inline const ::std::string& Type_Name(Type value) {
     return FieldDescriptorProto_Type_Name(value);
     return FieldDescriptorProto_Type_Name(value);
   }
   }
@@ -738,22 +743,22 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
       Type* value) {
       Type* value) {
     return FieldDescriptorProto_Type_Parse(name, 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;
   typedef FieldDescriptorProto_Label Label;
   static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
   static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
   static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
   static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
   static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED;
   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*
   static inline const ::google::protobuf::EnumDescriptor*
   Label_descriptor() {
   Label_descriptor() {
     return FieldDescriptorProto_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) {
   static inline const ::std::string& Label_Name(Label value) {
     return FieldDescriptorProto_Label_Name(value);
     return FieldDescriptorProto_Label_Name(value);
   }
   }
@@ -761,10 +766,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
       Label* value) {
       Label* value) {
     return FieldDescriptorProto_Label_Parse(name, 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 -------------------------------------------------------
   // accessors -------------------------------------------------------
   
   
@@ -855,6 +856,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -920,8 +922,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -965,6 +966,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1030,8 +1032,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1072,6 +1073,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1137,8 +1139,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1182,6 +1183,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1247,8 +1249,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1305,6 +1306,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1370,21 +1372,25 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
   typedef FileOptions_OptimizeMode OptimizeMode;
   typedef FileOptions_OptimizeMode OptimizeMode;
   static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
   static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
   static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
   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*
   static inline const ::google::protobuf::EnumDescriptor*
   OptimizeMode_descriptor() {
   OptimizeMode_descriptor() {
     return FileOptions_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) {
   static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) {
     return FileOptions_OptimizeMode_Name(value);
     return FileOptions_OptimizeMode_Name(value);
   }
   }
@@ -1392,10 +1398,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
       OptimizeMode* value) {
       OptimizeMode* value) {
     return FileOptions_OptimizeMode_Parse(name, 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 -------------------------------------------------------
   // accessors -------------------------------------------------------
   
   
@@ -1459,6 +1461,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1524,8 +1527,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1538,6 +1540,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
   inline bool message_set_wire_format() const;
   inline bool message_set_wire_format() const;
   inline void set_message_set_wire_format(bool value);
   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;
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
   inline void clear_uninterpreted_option();
@@ -1555,11 +1564,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
   mutable int _cached_size_;
   mutable int _cached_size_;
   
   
   bool message_set_wire_format_;
   bool message_set_wire_format_;
+  bool no_standard_descriptor_accessor_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_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 != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   inline bool _has_bit(int index) const {
   inline bool _has_bit(int index) const {
@@ -1624,21 +1635,24 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
   typedef FieldOptions_CType CType;
   typedef FieldOptions_CType CType;
   static const CType CORD = FieldOptions_CType_CORD;
   static const CType CORD = FieldOptions_CType_CORD;
   static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
   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*
   static inline const ::google::protobuf::EnumDescriptor*
   CType_descriptor() {
   CType_descriptor() {
     return FieldOptions_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) {
   static inline const ::std::string& CType_Name(CType value) {
     return FieldOptions_CType_Name(value);
     return FieldOptions_CType_Name(value);
   }
   }
@@ -1646,10 +1660,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
       CType* value) {
       CType* value) {
     return FieldOptions_CType_Parse(name, 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 -------------------------------------------------------
   // accessors -------------------------------------------------------
   
   
@@ -1709,6 +1719,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1774,8 +1785,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1801,6 +1811,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1866,8 +1877,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1893,6 +1903,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1958,8 +1969,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -1985,6 +1995,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2050,8 +2061,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -2077,6 +2087,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2142,8 +2153,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -2176,6 +2186,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_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_[(2 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2241,8 +2252,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
   void SetCachedSize(int size) const { _cached_size_ = size; }
   void SetCachedSize(int size) const { _cached_size_ = size; }
   public:
   public:
   
   
-  const ::google::protobuf::Descriptor* GetDescriptor() const;
-  const ::google::protobuf::Reflection* GetReflection() const;
+  ::google::protobuf::Metadata GetMetadata() const;
   
   
   // nested types ----------------------------------------------------
   // nested types ----------------------------------------------------
   
   
@@ -2316,6 +2326,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
   ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
   ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
   
   
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
   // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -3647,6 +3658,22 @@ inline void MessageOptions::set_message_set_wire_format(bool value) {
   message_set_wire_format_ = value;
   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;
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int MessageOptions::uninterpreted_option_size() const {
 inline int MessageOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
   return uninterpreted_option_.size();
@@ -4134,4 +4161,30 @@ inline ::std::string* UninterpretedOption::mutable_string_value() {
 
 
 }  // namespace protobuf
 }  // namespace protobuf
 }  // namespace google
 }  // 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
 #endif  // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED

+ 9 - 2
src/google/protobuf/descriptor.proto

@@ -247,8 +247,10 @@ message FileOptions {
 
 
   // Generated classes can be optimized for speed or code size.
   // Generated classes can be optimized for speed or code size.
   enum OptimizeMode {
   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];
   optional OptimizeMode optimize_for = 9 [default=SPEED];
 
 
@@ -282,6 +284,11 @@ message MessageOptions {
   // the protocol compiler.
   // the protocol compiler.
   optional bool message_set_wire_format = 1 [default=false];
   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.
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
   repeated UninterpretedOption uninterpreted_option = 999;
 
 

+ 145 - 0
src/google/protobuf/descriptor_unittest.cc

@@ -2135,6 +2135,83 @@ TEST(CustomOptions, OptionsFromOtherFile) {
   EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
   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 @@ TEST_F(ValidationErrorTest, UnknownDependency) {
     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
     "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) {
 TEST_F(ValidationErrorTest, DupeFile) {
   BuildFile(
   BuildFile(
     "name: \"foo.proto\" "
     "name: \"foo.proto\" "
@@ -3345,6 +3446,50 @@ TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) {
     "message type.\n");
     "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) {
 TEST_F(ValidationErrorTest, RollbackAfterError) {
   // Build a file which contains every kind of construct but references an
   // Build a file which contains every kind of construct but references an
   // undefined type.  All these constructs will be added to the symbol table
   // undefined type.  All these constructs will be added to the symbol table

+ 43 - 41
src/google/protobuf/dynamic_message.cc

@@ -70,6 +70,7 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/repeated_field.h>
@@ -82,7 +83,6 @@ namespace protobuf {
 using internal::WireFormat;
 using internal::WireFormat;
 using internal::ExtensionSet;
 using internal::ExtensionSet;
 using internal::GeneratedMessageReflection;
 using internal::GeneratedMessageReflection;
-using internal::GenericRepeatedField;
 
 
 
 
 // ===================================================================
 // ===================================================================
@@ -186,8 +186,7 @@ class DynamicMessage : public Message {
   int GetCachedSize() const;
   int GetCachedSize() const;
   void SetCachedSize(int size) const;
   void SetCachedSize(int size) const;
 
 
-  const Descriptor* GetDescriptor() const;
-  const Reflection* GetReflection() const;
+  Metadata GetMetadata() const;
 
 
  private:
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -279,20 +278,10 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
         break;
         break;
 
 
       case FieldDescriptor::CPPTYPE_MESSAGE: {
       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;
         break;
       }
       }
@@ -322,9 +311,33 @@ DynamicMessage::~DynamicMessage() {
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
 
 
     if (field->is_repeated()) {
     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) {
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
         string* ptr = *reinterpret_cast<string**>(field_ptr);
         string* ptr = *reinterpret_cast<string**>(field_ptr);
@@ -353,24 +366,14 @@ void DynamicMessage::CrossLinkPrototypes() {
     const FieldDescriptor* field = descriptor->field(i);
     const FieldDescriptor* field = descriptor->field(i);
     void* field_ptr = OffsetToPointer(type_info_->offsets[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
       // For fields with message types, we need to cross-link with the
       // prototype for the field's type.
       // 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());
         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 @@ void DynamicMessage::SetCachedSize(int size) const {
   cached_byte_size_ = size;
   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;
 }
 }
 
 
 // ===================================================================
 // ===================================================================

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 361 - 232
src/google/protobuf/extension_set.cc


+ 97 - 47
src/google/protobuf/extension_set.h

@@ -45,20 +45,23 @@
 #include <string>
 #include <string>
 
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/message.h>
 
 
 namespace google {
 namespace google {
+
 namespace protobuf {
 namespace protobuf {
   class Descriptor;                                    // descriptor.h
   class Descriptor;                                    // descriptor.h
   class FieldDescriptor;                               // descriptor.h
   class FieldDescriptor;                               // descriptor.h
   class DescriptorPool;                                // descriptor.h
   class DescriptorPool;                                // descriptor.h
-  class Message;                                       // message.h
+  class MessageLite;                                   // message_lite.h
   class MessageFactory;                                // message.h
   class MessageFactory;                                // message.h
   class UnknownFieldSet;                               // unknown_field_set.h
   class UnknownFieldSet;                               // unknown_field_set.h
   namespace io {
   namespace io {
     class CodedInputStream;                              // coded_stream.h
     class CodedInputStream;                              // coded_stream.h
     class CodedOutputStream;                             // 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 RepeatedField;     // repeated_field.h
   template <typename Element> class RepeatedPtrField;  // repeated_field.h
   template <typename Element> class RepeatedPtrField;  // repeated_field.h
 }
 }
@@ -66,9 +69,9 @@ namespace protobuf {
 namespace protobuf {
 namespace protobuf {
 namespace internal {
 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.
 // ExtensionSet::Extension small.
 typedef uint8 FieldType;
 typedef uint8 FieldType;
 
 
@@ -98,17 +101,17 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   // to look up extensions for parsed field numbers.  Note that dynamic parsing
   // to look up extensions for parsed field numbers.  Note that dynamic parsing
   // does not use ParseField(); only protocol-compiler-generated parsing
   // does not use ParseField(); only protocol-compiler-generated parsing
   // methods do.
   // methods do.
-  static void RegisterExtension(const Message* containing_type,
+  static void RegisterExtension(const MessageLite* containing_type,
                                 int number, FieldType type,
                                 int number, FieldType type,
                                 bool is_repeated, bool is_packed);
                                 bool is_repeated, bool is_packed);
-  static void RegisterEnumExtension(const Message* containing_type,
+  static void RegisterEnumExtension(const MessageLite* containing_type,
                                     int number, FieldType type,
                                     int number, FieldType type,
                                     bool is_repeated, bool is_packed,
                                     bool is_repeated, bool is_packed,
                                     EnumValidityFunc* is_valid);
                                     EnumValidityFunc* is_valid);
-  static void RegisterMessageExtension(const Message* containing_type,
+  static void RegisterMessageExtension(const MessageLite* containing_type,
                                        int number, FieldType type,
                                        int number, FieldType type,
                                        bool is_repeated, bool is_packed,
                                        bool is_repeated, bool is_packed,
-                                       const Message* prototype);
+                                       const MessageLite* prototype);
 
 
   // =================================================================
   // =================================================================
 
 
@@ -167,9 +170,10 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   bool   GetBool  (int number, bool   default_value) const;
   bool   GetBool  (int number, bool   default_value) const;
   int    GetEnum  (int number, int    default_value) const;
   int    GetEnum  (int number, int    default_value) const;
   const string & GetString (int number, const string&  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 SetInt32 (int number, FieldType type, int32  value);
   void SetInt64 (int number, FieldType type, int64  value);
   void SetInt64 (int number, FieldType type, int64  value);
@@ -181,11 +185,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   void SetEnum  (int number, FieldType type, int    value);
   void SetEnum  (int number, FieldType type, int    value);
   void SetString(int number, FieldType type, const string& value);
   void SetString(int number, FieldType type, const string& value);
   string * MutableString (int number, FieldType type);
   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 -------------------------------------------------
   // repeated fields -------------------------------------------------
 
 
@@ -198,7 +202,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   bool   GetRepeatedBool  (int number, int index) const;
   bool   GetRepeatedBool  (int number, int index) const;
   int    GetRepeatedEnum  (int number, int index) const;
   int    GetRepeatedEnum  (int number, int index) const;
   const string & GetRepeatedString (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 SetRepeatedInt32 (int number, int index, int32  value);
   void SetRepeatedInt64 (int number, int index, int64  value);
   void SetRepeatedInt64 (int number, int index, int64  value);
@@ -210,7 +214,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   void SetRepeatedEnum  (int number, int index, int    value);
   void SetRepeatedEnum  (int number, int index, int    value);
   void SetRepeatedString(int number, int index, const string& value);
   void SetRepeatedString(int number, int index, const string& value);
   string * MutableRepeatedString (int number, int index);
   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 AddInt32 (int number, FieldType type, bool packed, int32  value);
   void AddInt64 (int number, FieldType type, bool packed, int64  value);
   void AddInt64 (int number, FieldType type, bool packed, int64  value);
@@ -222,11 +226,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   void AddEnum  (int number, FieldType type, bool packed, int    value);
   void AddEnum  (int number, FieldType type, bool packed, int    value);
   void AddString(int number, FieldType type, const string& value);
   void AddString(int number, FieldType type, const string& value);
   string * AddString (int number, FieldType type);
   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 RemoveLast(int number);
   void SwapElements(int number, int index1, int index2);
   void SwapElements(int number, int index1, int index2);
@@ -252,9 +256,31 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   // methods of ExtensionSet, this only works for generated message types --
   // methods of ExtensionSet, this only works for generated message types --
   // it looks up extensions registered using RegisterExtension().
   // it looks up extensions registered using RegisterExtension().
   bool ParseField(uint32 tag, io::CodedInputStream* input,
   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);
                   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
   // Write all extension fields with field numbers in the range
   //   [start_field_number, end_field_number)
   //   [start_field_number, end_field_number)
   // to the output stream, using the cached sizes computed when ByteSize() was
   // to the output stream, using the cached sizes computed when ByteSize() was
@@ -272,37 +298,50 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
                                          int end_field_number,
                                          int end_field_number,
                                          uint8* target) const;
                                          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.
   // Returns the total serialized size of all the extensions.
   int ByteSize() const;
   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
   // 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;
   int SpaceUsedExcludingSelf() const;
 
 
  private:
  private:
+
   struct Extension {
   struct Extension {
     union {
     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;
-
-      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;
+      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<MessageLite>* repeated_message_value;
     };
     };
 
 
     FieldType type;
     FieldType type;
@@ -328,7 +367,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
     void SerializeFieldWithCachedSizes(
     void SerializeFieldWithCachedSizes(
         int number,
         int number,
         io::CodedOutputStream* output) const;
         io::CodedOutputStream* output) const;
+    void SerializeMessageSetItemWithCachedSizes(
+        int number,
+        io::CodedOutputStream* output) const;
     int ByteSize(int number) const;
     int ByteSize(int number) const;
+    int MessageSetItemByteSize(int number) const;
     void Clear();
     void Clear();
     int GetSize() const;
     int GetSize() const;
     void Free();
     void Free();
@@ -339,6 +382,13 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
   // already exist.  Returns true if the extension did not already exist.
   // already exist.  Returns true if the extension did not already exist.
   bool MaybeNewExtension(int number, Extension** result);
   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
   // 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
   // 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
   // a map rather than hash_map here because we expect most ExtensionSets will

+ 218 - 0
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

+ 243 - 58
src/google/protobuf/generated_message_reflection.cc

@@ -38,6 +38,7 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 
 
 namespace google {
 namespace google {
@@ -220,8 +221,36 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldDescriptor* field = descriptor_->field(i);
 
 
     if (field->is_repeated()) {
     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 {
     } else {
       switch (field->cpp_type()) {
       switch (field->cpp_type()) {
         case FieldDescriptor::CPPTYPE_INT32 :
         case FieldDescriptor::CPPTYPE_INT32 :
@@ -274,25 +303,59 @@ void GeneratedMessageReflection::Swap(
     Message* message2) const {
     Message* message2) const {
   if (message1 == message2) return;
   if (message1 == message2) return;
 
 
+  // TODO(kenton):  Other Reflection methods should probably check this too.
   GOOGLE_CHECK_EQ(message1->GetReflection(), this)
   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)
   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_bits1 = MutableHasBits(message1);
   uint32* has_bits2 = MutableHasBits(message2);
   uint32* has_bits2 = MutableHasBits(message2);
   int has_bits_size = (descriptor_->field_count() + 31) / 32;
   int has_bits_size = (descriptor_->field_count() + 31) / 32;
 
 
   for (int i = 0; i < has_bits_size; i++) {
   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++) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->is_repeated()) {
     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 {
     } else {
       switch (field->cpp_type()) {
       switch (field->cpp_type()) {
 #define SWAP_VALUES(CPPTYPE, TYPE)                                           \
 #define SWAP_VALUES(CPPTYPE, TYPE)                                           \
@@ -300,6 +363,7 @@ void GeneratedMessageReflection::Swap(
           swap(*MutableRaw<TYPE>(message1, field),                           \
           swap(*MutableRaw<TYPE>(message1, field),                           \
                *MutableRaw<TYPE>(message2, field));                          \
                *MutableRaw<TYPE>(message2, field));                          \
           break;
           break;
+
           SWAP_VALUES(INT32 , int32 );
           SWAP_VALUES(INT32 , int32 );
           SWAP_VALUES(INT64 , int64 );
           SWAP_VALUES(INT64 , int64 );
           SWAP_VALUES(UINT32, uint32);
           SWAP_VALUES(UINT32, uint32);
@@ -307,10 +371,15 @@ void GeneratedMessageReflection::Swap(
           SWAP_VALUES(FLOAT , float );
           SWAP_VALUES(FLOAT , float );
           SWAP_VALUES(DOUBLE, double);
           SWAP_VALUES(DOUBLE, double);
           SWAP_VALUES(BOOL  , bool  );
           SWAP_VALUES(BOOL  , bool  );
-          SWAP_VALUES(ENUM  , int32 );
-          SWAP_VALUES(STRING, string*);
+          SWAP_VALUES(ENUM  , int   );
           SWAP_VALUES(MESSAGE, Message*);
           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:
         default:
           GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
           GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
       }
       }
@@ -346,7 +415,28 @@ int GeneratedMessageReflection::FieldSize(const Message& message,
   if (field->is_extension()) {
   if (field->is_extension()) {
     return GetExtensionSet(message).ExtensionSize(field->number());
     return GetExtensionSet(message).ExtensionSize(field->number());
   } else {
   } 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 @@ void GeneratedMessageReflection::ClearField(
       }
       }
     }
     }
   } else {
   } 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 @@ void GeneratedMessageReflection::RemoveLast(
   if (field->is_extension()) {
   if (field->is_extension()) {
     MutableExtensionSet(message)->RemoveLast(field->number());
     MutableExtensionSet(message)->RemoveLast(field->number());
   } else {
   } 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 @@ void GeneratedMessageReflection::SwapElements(
   USAGE_CHECK_REPEATED(Swap);
   USAGE_CHECK_REPEATED(Swap);
 
 
   if (field->is_extension()) {
   if (field->is_extension()) {
-    MutableExtensionSet(message)->SwapElements(
-                                      field->number(), index1, index2);
+    MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
   } else {
   } 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 @@ void GeneratedMessageReflection::ListFields(
   for (int i = 0; i < descriptor_->field_count(); i++) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->is_repeated()) {
     if (field->is_repeated()) {
-      if (GetRaw<GenericRepeatedField>(message, field).GenericSize() > 0) {
+      if (FieldSize(message, field) > 0) {
         output->push_back(field);
         output->push_back(field);
       }
       }
     } else {
     } else {
@@ -597,7 +759,7 @@ string GeneratedMessageReflection::GetRepeatedString(
   if (field->is_extension()) {
   if (field->is_extension()) {
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
   } else {
   } else {
-    return GetRepeatedField<string>(message, field, index);
+    return GetRepeatedPtrField<string>(message, field, index);
   }
   }
 }
 }
 
 
@@ -608,7 +770,7 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference(
   if (field->is_extension()) {
   if (field->is_extension()) {
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
   } else {
   } else {
-    return GetRepeatedField<string>(message, field, index);
+    return GetRepeatedPtrField<string>(message, field, index);
   }
   }
 }
 }
 
 
@@ -621,7 +783,7 @@ void GeneratedMessageReflection::SetRepeatedString(
     MutableExtensionSet(message)->SetRepeatedString(
     MutableExtensionSet(message)->SetRepeatedString(
       field->number(), index, value);
       field->number(), index, value);
   } else {
   } else {
-    SetRepeatedField<string>(message, field, index, value);
+    *MutableRepeatedField<string>(message, field, index) = value;
   }
   }
 }
 }
 
 
@@ -634,7 +796,7 @@ void GeneratedMessageReflection::AddString(
     MutableExtensionSet(message)->AddString(field->number(),
     MutableExtensionSet(message)->AddString(field->number(),
                                             field->type(), value);
                                             field->type(), value);
   } else {
   } else {
-    AddField<string>(message, field, value);
+    *AddField<string>(message, field) = value;
   }
   }
 }
 }
 
 
@@ -725,9 +887,10 @@ const Message& GeneratedMessageReflection::GetMessage(
   USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
   USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
 
 
   if (field->is_extension()) {
   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 {
   } else {
     const Message* result = GetRaw<const Message*>(message, field);
     const Message* result = GetRaw<const Message*>(message, field);
     if (result == NULL) {
     if (result == NULL) {
@@ -742,10 +905,11 @@ Message* GeneratedMessageReflection::MutableMessage(
   USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
   USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
 
 
   if (field->is_extension()) {
   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 {
   } else {
     Message** result = MutableField<Message*>(message, field);
     Message** result = MutableField<Message*>(message, field);
     if (*result == NULL) {
     if (*result == NULL) {
@@ -761,9 +925,11 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage(
   USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
   USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
 
 
   if (field->is_extension()) {
   if (field->is_extension()) {
-    return GetExtensionSet(message).GetRepeatedMessage(field->number(), index);
+    return static_cast<const Message&>(
+        GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
   } else {
   } else {
-    return GetRepeatedField<Message>(message, field, index);
+    return GetRaw<RepeatedPtrFieldBase>(message, field)
+        .Get<GenericTypeHandler<Message> >(index);
   }
   }
 }
 }
 
 
@@ -772,10 +938,12 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
   USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
   USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
 
 
   if (field->is_extension()) {
   if (field->is_extension()) {
-    return MutableExtensionSet(message)->MutableRepeatedMessage(
-      field->number(), index);
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->MutableRepeatedMessage(
+          field->number(), index));
   } else {
   } else {
-    return MutableRepeatedField<Message>(message, field, index);
+    return MutableRaw<RepeatedPtrFieldBase>(message, field)
+        ->Mutable<GenericTypeHandler<Message> >(index);
   }
   }
 }
 }
 
 
@@ -784,12 +952,29 @@ Message* GeneratedMessageReflection::AddMessage(
   USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
   USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
 
 
   if (field->is_extension()) {
   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 {
   } 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 @@ inline Type* GeneratedMessageReflection::MutableField(
 }
 }
 
 
 template <typename Type>
 template <typename Type>
-inline const Type& GeneratedMessageReflection::GetRepeatedField(
+inline Type GeneratedMessageReflection::GetRepeatedField(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  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 {
     const Message& message, const FieldDescriptor* field, int index) const {
-  return *reinterpret_cast<const Type*>(
-    GetRaw<GenericRepeatedField>(message, field).GenericGet(index));
+  return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
 }
 }
 
 
 template <typename Type>
 template <typename Type>
 inline void GeneratedMessageReflection::SetRepeatedField(
 inline void GeneratedMessageReflection::SetRepeatedField(
     Message* message, const FieldDescriptor* field,
     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>
 template <typename Type>
 inline Type* GeneratedMessageReflection::MutableRepeatedField(
 inline Type* GeneratedMessageReflection::MutableRepeatedField(
     Message* message, const FieldDescriptor* field, int index) const {
     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>
 template <typename Type>
 inline void GeneratedMessageReflection::AddField(
 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>
 template <typename Type>
 inline Type* GeneratedMessageReflection::AddField(
 inline Type* GeneratedMessageReflection::AddField(
     Message* message, const FieldDescriptor* field) const {
     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 internal
 }  // namespace protobuf
 }  // namespace protobuf
 }  // namespace google
 }  // namespace google

+ 10 - 12
src/google/protobuf/generated_message_reflection.h

@@ -142,7 +142,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
   void ClearField(Message* message, const FieldDescriptor* field) const;
   void ClearField(Message* message, const FieldDescriptor* field) const;
   void RemoveLast(Message* message, const FieldDescriptor* field) const;
   void RemoveLast(Message* message, const FieldDescriptor* field) const;
   void Swap(Message* message1, Message* message2) 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;
             int index1, int index2) const;
   void ListFields(const Message& message,
   void ListFields(const Message& message,
                   vector<const FieldDescriptor*>* output) const;
                   vector<const FieldDescriptor*>* output) const;
@@ -314,20 +314,24 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
   inline Type* MutableField(Message* message,
   inline Type* MutableField(Message* message,
                             const FieldDescriptor* field) const;
                             const FieldDescriptor* field) const;
   template <typename Type>
   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>
   template <typename Type>
   inline void SetRepeatedField(Message* message,
   inline void SetRepeatedField(Message* message,
                                const FieldDescriptor* field, int index,
                                const FieldDescriptor* field, int index,
-                               const Type& value) const;
+                               Type value) const;
   template <typename Type>
   template <typename Type>
   inline Type* MutableRepeatedField(Message* message,
   inline Type* MutableRepeatedField(Message* message,
                                     const FieldDescriptor* field,
                                     const FieldDescriptor* field,
                                     int index) const;
                                     int index) const;
   template <typename Type>
   template <typename Type>
   inline void AddField(Message* message,
   inline void AddField(Message* message,
-                       const FieldDescriptor* field, const Type& value) const;
+                       const FieldDescriptor* field, Type value) const;
   template <typename Type>
   template <typename Type>
   inline Type* AddField(Message* message,
   inline Type* AddField(Message* message,
                         const FieldDescriptor* field) const;
                         const FieldDescriptor* field) const;
@@ -388,11 +392,6 @@ inline To dynamic_cast_if_available(From from) {
 #endif
 #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
 // 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,
 // enum name of the given type, returning true and filling in value on success,
 // or returning false and leaving value unchanged on failure.
 // or returning false and leaving value unchanged on failure.
@@ -415,7 +414,6 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor,
 // descriptor.h.
 // descriptor.h.
 LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
 LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
 
 
-
 }  // namespace internal
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace protobuf
 
 

+ 44 - 0
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

+ 65 - 0
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__

+ 46 - 50
src/google/protobuf/io/coded_stream.cc

@@ -80,18 +80,49 @@ CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
     total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
     total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
     recursion_depth_(0),
     recursion_depth_(0),
     recursion_limit_(kDefaultRecursionLimit) {
     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() {
 CodedInputStream::~CodedInputStream() {
+  if (input_ != NULL) {
+    BackUpInputToCurrentPosition();
+  }
+}
+
+
+void CodedInputStream::BackUpInputToCurrentPosition() {
   int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
   int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
   if (backup_bytes > 0) {
   if (backup_bytes > 0) {
-    // We still have bytes left over from the last buffer.  Back up over
-    // them.
     input_->BackUp(backup_bytes);
     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() {
 inline void CodedInputStream::RecomputeBufferLimits() {
   buffer_size_ += buffer_size_after_limit_;
   buffer_size_ += buffer_size_after_limit_;
   int closest_limit = min(current_limit_, total_bytes_limit_);
   int closest_limit = min(current_limit_, total_bytes_limit_);
@@ -193,8 +224,10 @@ bool CodedInputStream::Skip(int count) {
   int bytes_until_limit = closest_limit - total_bytes_read_;
   int bytes_until_limit = closest_limit - total_bytes_read_;
   if (bytes_until_limit < count) {
   if (bytes_until_limit < count) {
     // We hit the limit.  Skip up to it then fail.
     // 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;
     return false;
   }
   }
 
 
@@ -216,6 +249,7 @@ bool CodedInputStream::ReadRaw(void* buffer, int size) {
     memcpy(buffer, buffer_, buffer_size_);
     memcpy(buffer, buffer_, buffer_size_);
     buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
     buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
     size -= buffer_size_;
     size -= buffer_size_;
+    Advance(buffer_size_);
     if (!Refresh()) return false;
     if (!Refresh()) return false;
   }
   }
 
 
@@ -247,6 +281,7 @@ bool CodedInputStream::ReadString(string* buffer, int size) {
       buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
       buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
     }
     }
     size -= buffer_size_;
     size -= buffer_size_;
+    Advance(buffer_size_);
     if (!Refresh()) return false;
     if (!Refresh()) return false;
   }
   }
 
 
@@ -441,11 +476,11 @@ bool CodedInputStream::ReadVarint64(uint64* value) {
 }
 }
 
 
 bool CodedInputStream::Refresh() {
 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_;
     int current_position = total_bytes_read_ - buffer_size_after_limit_;
 
 
     if (current_position >= total_bytes_limit_ &&
     if (current_position >= total_bytes_limit_ &&
@@ -570,10 +605,7 @@ void CodedOutputStream::WriteLittleEndian32(uint32 value) {
   bool use_fast = buffer_size_ >= sizeof(value);
   bool use_fast = buffer_size_ >= sizeof(value);
   uint8* ptr = use_fast ? buffer_ : bytes;
   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) {
   if (use_fast) {
     Advance(sizeof(value));
     Advance(sizeof(value));
@@ -582,32 +614,13 @@ void CodedOutputStream::WriteLittleEndian32(uint32 value) {
   }
   }
 }
 }
 
 
-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) {
 void CodedOutputStream::WriteLittleEndian64(uint64 value) {
   uint8 bytes[sizeof(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);
   bool use_fast = buffer_size_ >= sizeof(value);
   uint8* ptr = use_fast ? buffer_ : bytes;
   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) {
   if (use_fast) {
     Advance(sizeof(value));
     Advance(sizeof(value));
@@ -616,23 +629,6 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) {
   }
   }
 }
 }
 
 
-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(
 inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
     uint32 value, uint8* target) {
     uint32 value, uint8* target) {
   target[0] = static_cast<uint8>(value | 0x80);
   target[0] = static_cast<uint8>(value | 0x80);

+ 46 - 0
src/google/protobuf/io/coded_stream.h

@@ -110,6 +110,9 @@
 #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
 #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
 
 
 #include <string>
 #include <string>
+#ifndef _MSC_VER
+#include <sys/param.h>
+#endif  // !_MSC_VER
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 
 
 namespace google {
 namespace google {
@@ -137,6 +140,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
   // Create a CodedInputStream that reads from the given ZeroCopyInputStream.
   // Create a CodedInputStream that reads from the given ZeroCopyInputStream.
   explicit CodedInputStream(ZeroCopyInputStream* input);
   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
   // Destroy the CodedInputStream and position the underlying
   // ZeroCopyInputStream at the first unread byte.  If an error occurred while
   // ZeroCopyInputStream at the first unread byte.  If an error occurred while
   // reading (causing a method to return false), then the exact position of
   // reading (causing a method to return false), then the exact position of
@@ -360,6 +368,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
   // Advance the buffer by a given number of bytes.
   // Advance the buffer by a given number of bytes.
   void Advance(int amount);
   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
   // Recomputes the value of buffer_size_after_limit_.  Must be called after
   // current_limit_ or total_bytes_limit_ changes.
   // current_limit_ or total_bytes_limit_ changes.
   void RecomputeBufferLimits();
   void RecomputeBufferLimits();
@@ -664,6 +675,41 @@ inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray(
   }
   }
 }
 }
 
 
+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) {
 inline void CodedOutputStream::WriteTag(uint32 value) {
   WriteVarint32(value);
   WriteVarint32(value);
 }
 }

+ 3 - 4
src/google/protobuf/io/gzip_stream.cc

@@ -1,5 +1,5 @@
 // Protocol Buffers - Google's data interchange format
 // 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/
 // http://code.google.com/p/protobuf/
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // 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.
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 // Author: brianolson@google.com (Brian Olson)
 // 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
 // This file contains the implementation of classes GzipInputStream and
 // GzipOutputStream.
 // GzipOutputStream.
@@ -39,6 +37,7 @@
 
 
 #if HAVE_ZLIB
 #if HAVE_ZLIB
 #include <google/protobuf/io/gzip_stream.h>
 #include <google/protobuf/io/gzip_stream.h>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 
 
 namespace google {
 namespace google {
@@ -291,6 +290,6 @@ bool GzipOutputStream::Close() {
 
 
 }  // namespace io
 }  // namespace io
 }  // namespace protobuf
 }  // namespace protobuf
-}  // namespace google
 
 
 #endif  // HAVE_ZLIB
 #endif  // HAVE_ZLIB
+}  // namespace google

+ 2 - 4
src/google/protobuf/io/gzip_stream.h

@@ -1,5 +1,5 @@
 // Protocol Buffers - Google's data interchange format
 // 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/
 // http://code.google.com/p/protobuf/
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // 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.
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 // Author: brianolson@google.com (Brian Olson)
 // 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
 // This file contains the definition for classes GzipInputStream and
 // GzipOutputStream.
 // GzipOutputStream.
@@ -173,6 +171,6 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
 
 
 }  // namespace io
 }  // namespace io
 }  // namespace protobuf
 }  // namespace protobuf
-}  // namespace google
 
 
+}  // namespace google
 #endif  // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
 #endif  // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__

+ 1 - 1
src/google/protobuf/io/tokenizer.cc

@@ -571,7 +571,7 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
   const char* ptr = text.c_str();
   const char* ptr = text.c_str();
   int base = 10;
   int base = 10;
   if (ptr[0] == '0') {
   if (ptr[0] == '0') {
-    if (ptr[1] == 'x') {
+    if (ptr[1] == 'x' || ptr[1] == 'X') {
       // This is hex.
       // This is hex.
       base = 16;
       base = 16;
       ptr += 2;
       ptr += 2;

+ 1 - 0
src/google/protobuf/io/tokenizer_unittest.cc

@@ -487,6 +487,7 @@ TEST_F(TokenizerTest, ParseInteger) {
   EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12"));
   EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12"));
   EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF"));
   EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF"));
   EXPECT_EQ(01234567, ParseInteger("01234567"));
   EXPECT_EQ(01234567, ParseInteger("01234567"));
+  EXPECT_EQ(0X123, ParseInteger("0X123"));
 
 
   // Test invalid integers that may still be tokenized as integers.
   // Test invalid integers that may still be tokenized as integers.
   EXPECT_EQ(0, ParseInteger("0x"));
   EXPECT_EQ(0, ParseInteger("0x"));

+ 0 - 345
src/google/protobuf/io/zero_copy_stream_impl.cc

@@ -60,7 +60,6 @@ namespace io {
 
 
 namespace {
 namespace {
 
 
-
 // EINTR sucks.
 // EINTR sucks.
 int close_no_eintr(int fd) {
 int close_no_eintr(int fd) {
   int result;
   int result;
@@ -70,352 +69,8 @@ int close_no_eintr(int fd) {
   return result;
   return result;
 }
 }
 
 
-// Default block size for Copying{In,Out}putStreamAdaptor.
-static const int kDefaultBlockSize = 8192;
-
 }  // namespace
 }  // 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();
-}
 
 
 // ===================================================================
 // ===================================================================
 
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio